1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
# -*- coding: UTF-8 -*-
#
require 'securerandom'
#
module Zorglub
#
class Node
#
def session
@session ||= Session.new @request, @response
end
end
#
class SessionHash
#
@data = {}
class << self
attr_reader :data
def sid_exists? sid
not @data[sid].nil?
end
end
#
attr_reader :sid
#
def initialize sid
@sid = sid
@session_data = SessionHash.data[sid]||={}
end
#
#
def [] idx
@session_data[idx]
end
#
def []= idx, v
@session_data[idx] = v
end
end
#
class Session
#
@key = 'zorglub.sid'
@kls = Zorglub::SessionHash
@sid_length = 64
#
class << self
attr_accessor :key, :kls, :sid_length
end
#
def initialize req, resp
@request = req
@response = resp
@instance = nil
end
#
def setup!
if Config.session_on
cookie = @request.cookies[Session.key]
if cookie.nil?
cookie = generate_sid
@response.set_cookie Session.key, cookie
end
@instance = Session.kls.new cookie
end
end
private :setup!
#
def sid
setup! if @instance.nil?
return nil if @instance.nil?
@instance.sid
end
#
def [] idx
setup! if @instance.nil?
return nil if @instance.nil?
@instance[idx]
end
#
def []= idx, v
setup! if @instance.nil?
return nil if @instance.nil?
@instance[idx] = v
end
#
def generate_sid
begin sid = sid_algorithm end while Session.kls.sid_exists? sid
sid
end
#
begin
require 'securerandom'
# Using SecureRandom, optional length.
# SecureRandom is available since Ruby 1.8.7.
# For Ruby versions earlier than that, you can require the uuidtools gem,
# which has a drop-in replacement for SecureRandom.
def sid_algorithm; SecureRandom.hex(Session.sid_length); end
rescue LoadError
require 'openssl'
# Using OpenSSL::Random for generation, this is comparable in performance
# with stdlib SecureRandom and also allows for optional length, it should
# have the same behaviour as the SecureRandom::hex method of the
# uuidtools gem.
def sid_algorithm
OpenSSL::Random.random_bytes(Session.sid_length / 2).unpack('H*')[0]
end
rescue LoadError
# Digest::SHA2::hexdigest produces a string of length 64, although
# collisions are not very likely, the entropy is still very low and
# length is not optional.
#
# Replacing it with OS-provided random data would take a lot of code and
# won't be as cross-platform as Ruby.
def sid_algorithm
entropy = [ srand, rand, Time.now.to_f, rand, $$, rand, object_id ]
Digest::SHA2.hexdigest(entropy.join)
end
end
#
end
#
end
#
# EOF
|