Skip to content

Commit

Permalink
use session id objects
Browse files Browse the repository at this point in the history
  • Loading branch information
tenderlove committed Dec 17, 2019
1 parent 7237b66 commit 3ab0277
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 15 deletions.
28 changes: 24 additions & 4 deletions lib/rack/session/abstract/id.rb
Expand Up @@ -19,6 +19,20 @@ def empty?; true; end
def nil?; true; end
end

class SessionId
attr_reader :public_id

def initialize(public_id)
@public_id = public_id
end

alias :cookie_value :public_id

def empty?; false; end
def to_s; raise; end
def inspect; public_id.inspect; end
end

module Abstract
ENV_SESSION_KEY = 'rack.session'.freeze
ENV_SESSION_OPTIONS_KEY = 'rack.session.options'.freeze
Expand Down Expand Up @@ -66,7 +80,11 @@ def each(&block)

def [](key)
load_for_read!
@data[key.to_s]
if key == "session_id"
id.public_id
else
@data[key.to_s]
end
end
alias :fetch :[]

Expand Down Expand Up @@ -247,11 +265,13 @@ def initialize_sid
# Monkey patch this to use custom methods for session id generation.

def generate_sid(secure = @sid_secure)
if secure
public_id = if secure
secure.hex(@sid_length)
else
"%0#{@sid_length}x" % Kernel.rand(2**@sidbits - 1)
end

SessionId.new(public_id)
rescue NotImplementedError
generate_sid(false)
end
Expand Down Expand Up @@ -281,7 +301,7 @@ def extract_session_id(env)
request = Rack::Request.new(env)
sid = request.cookies[@key]
sid ||= request.params[@key] unless @cookie_only
sid || NullSessionId.new
(sid && SessionId.new(sid)) || NullSessionId.new
end

# Returns the current session id from the SessionHash.
Expand Down Expand Up @@ -353,7 +373,7 @@ def commit_session(env, status, headers, body)
env["rack.errors"].puts("Deferring cookie for #{session_id}") if $VERBOSE
else
cookie = Hash.new
cookie[:value] = data
cookie[:value] = data.cookie_value
cookie[:expires] = Time.now + options[:expire_after] if options[:expire_after]
cookie[:expires] = Time.now + options[:max_age] if options[:max_age]
set_cookie(env, headers, cookie.merge!(options))
Expand Down
11 changes: 10 additions & 1 deletion lib/rack/session/cookie.rb
Expand Up @@ -151,6 +151,15 @@ def persistent_session_id!(data, sid=nil)
data
end

class SessionId < DelegateClass(Session::SessionId)
attr_reader :cookie_value

def initialize(session_id, cookie_value)
super(session_id)
@cookie_value = cookie_value
end
end

def set_session(env, session_id, session, options)
session = session.merge("session_id" => session_id)
session_data = coder.encode(session)
Expand All @@ -163,7 +172,7 @@ def set_session(env, session_id, session, options)
env["rack.errors"].puts("Warning! Rack::Session::Cookie data size exceeds 4K.")
nil
else
session_data
SessionId.new(session_id, session_data)
end
end

Expand Down
10 changes: 5 additions & 5 deletions lib/rack/session/memcache.rb
Expand Up @@ -42,15 +42,15 @@ def initialize(app, options={})
def generate_sid
loop do
sid = super
break sid unless @pool.get(sid, true)
break sid unless @pool.get(sid.public_id, true)
end
end

def get_session(env, sid)
with_lock(env) do
unless sid and session = @pool.get(sid)
unless !sid.nil? and session = @pool.get(sid.public_id)
sid, session = generate_sid, {}
unless /^STORED/ =~ @pool.add(sid, session)
unless /^STORED/ =~ @pool.add(sid.public_id, session)
raise "Session collision on '#{sid.inspect}'"
end
end
Expand All @@ -63,14 +63,14 @@ def set_session(env, session_id, new_session, options)
expiry = expiry.nil? ? 0 : expiry + 1

with_lock(env) do
@pool.set session_id, new_session, expiry
@pool.set session_id.public_id, new_session, expiry
session_id
end
end

def destroy_session(env, session_id, options)
with_lock(env) do
@pool.delete(session_id)
@pool.delete(session_id.public_id)
generate_sid unless options[:drop]
end
end
Expand Down
8 changes: 4 additions & 4 deletions lib/rack/session/pool.rb
Expand Up @@ -43,24 +43,24 @@ def generate_sid

def get_session(env, sid)
with_lock(env) do
unless sid and session = @pool[sid]
unless !sid.nil? and session = @pool[sid.public_id]
sid, session = generate_sid, {}
@pool.store sid, session
@pool.store sid.public_id, session
end
[sid, session]
end
end

def set_session(env, session_id, new_session, options)
with_lock(env) do
@pool.store session_id, new_session
@pool.store session_id.public_id, new_session
session_id
end
end

def destroy_session(env, session_id, options)
with_lock(env) do
@pool.delete(session_id)
@pool.delete(session_id.public_id)
if options[:drop]
NullSessionId.new
else
Expand Down
2 changes: 1 addition & 1 deletion test/spec_session_abstract_id.rb
Expand Up @@ -47,7 +47,7 @@ def hex(*args)
end
end
id = Rack::Session::Abstract::ID.new nil, :secure_random => secure_random.new
id.send(:generate_sid).should.eql 'fake_hex'
id.send(:generate_sid).public_id.must_equal 'fake_hex'
end

end

0 comments on commit 3ab0277

Please sign in to comment.