lib/rack/session/abstract/id.rb in rack-2.0.7 vs lib/rack/session/abstract/id.rb in rack-2.0.8
- old
+ new
@@ -4,15 +4,42 @@
require 'rack'
require 'time'
require 'rack/request'
require 'rack/response'
require 'securerandom'
+require 'digest/sha2'
module Rack
module Session
+ class SessionId
+ ID_VERSION = 2
+
+ attr_reader :public_id
+
+ def initialize(public_id)
+ @public_id = public_id
+ end
+
+ def private_id
+ "#{ID_VERSION}::#{hash_sid(public_id)}"
+ end
+
+ alias :cookie_value :public_id
+
+ def empty?; false; end
+ def to_s; raise; end
+ def inspect; public_id.inspect; end
+
+ private
+
+ def hash_sid(sid)
+ Digest::SHA256.hexdigest(sid)
+ end
+ end
+
module Abstract
# SessionHash is responsible to lazily load the session from store.
class SessionHash
include Enumerable
@@ -355,18 +382,22 @@
req.get_header(RACK_ERRORS).puts("Warning! #{self.class.name} failed to save session. Content dropped.")
elsif options[:defer] and not options[:renew]
req.get_header(RACK_ERRORS).puts("Deferring cookie for #{session_id}") if $VERBOSE
else
cookie = Hash.new
- cookie[:value] = data
+ cookie[:value] = cookie_value(data)
cookie[:expires] = Time.now + options[:expire_after] if options[:expire_after]
cookie[:expires] = Time.now + options[:max_age] if options[:max_age]
set_cookie(req, res, cookie.merge!(options))
end
end
public :commit_session
+ def cookie_value(data)
+ data
+ end
+
# Sets the cookie back to the client with session id. We skip the cookie
# setting if the value didn't change (sid is the same) or expires was given.
def set_cookie(request, res, cookie)
if request.cookies[@key] != cookie[:value] || cookie[:expires]
@@ -401,9 +432,43 @@
# All thread safety and session destroy procedures should occur here.
# Should return a new session id or nil if options[:drop]
def delete_session(req, sid, options)
raise '#delete_session not implemented'
+ end
+ end
+
+ class PersistedSecure < Persisted
+ class SecureSessionHash < SessionHash
+ def [](key)
+ if key == "session_id"
+ load_for_read!
+ id.public_id
+ else
+ super
+ end
+ end
+ end
+
+ def generate_sid(*)
+ public_id = super
+
+ SessionId.new(public_id)
+ end
+
+ def extract_session_id(*)
+ public_id = super
+ public_id && SessionId.new(public_id)
+ end
+
+ private
+
+ def session_class
+ SecureSessionHash
+ end
+
+ def cookie_value(data)
+ data.cookie_value
end
end
class ID < Persisted
def self.inherited(klass)