0
@@ -33,6 +33,11 @@ require 'openssl' # to generate the HMAC message digest
0
# integrity defaults to 'SHA1' but may be any digest provided by OpenSSL,
0
# such as 'MD5', 'RIPEMD160', 'SHA256', etc.
0
+# * <tt>:stable_session_id</tt>: The Cookie Session Store doesn't maintain any server side
0
+# state by default.A unique session identifier is spawned per request, which may not be
0
+# desireable for some applications.Set :stable_session_id to true to maintain a stable
0
+# session identifier within the cookie.
0
# To generate a secret key for an existing application, run
0
# "rake secret" and set the key in config/environment.rb.
0
@@ -50,6 +55,7 @@ class CGI::Session::CookieStore
0
# Called from CGI::Session only.
0
def initialize(session, options = {})
0
+ options.reverse_merge!( 'stable_session_id' => false )
0
# The session_key option is required.
0
if options['session_key'].blank?
0
raise ArgumentError, 'A session_key is required to write a cookie containing the session data. Use config.action_controller.session = { :session_key => "_myapp_session", :secret => "some secret phrase" } in config/environment.rb'
0
@@ -59,7 +65,7 @@ class CGI::Session::CookieStore
0
ensure_secret_secure(options['secret'])
0
# Keep the session and its secret on hand so we can read and write cookies.
0
- @session, @secret
= session, options['secret']
0
+ @session, @secret
, @stable_session_id = session, options['secret'], options['stable_session_id']
0
# Message digest defaults to SHA1.
0
@digest = options['digest'] || 'SHA1'
0
@@ -129,6 +135,7 @@ class CGI::Session::CookieStore
0
# Marshal a session hash into safe cookie data. Include an integrity hash.
0
+ session = stable_session_id!( session )
0
data = ActiveSupport::Base64.encode64(Marshal.dump(session)).chop
0
"#{data}--#{generate_digest(data)}"
0
@@ -144,10 +151,25 @@ class CGI::Session::CookieStore
0
raise TamperedWithCookie
0
- Marshal.load(ActiveSupport::Base64.decode64(data))
0
+ returning( stable_session_id!( Marshal.load(ActiveSupport::Base64.decode64(data)) ) ) do |data|
0
+ @session.instance_variable_set(:@session_id, data[:session_id]) if @stable_session_id
0
+ def stable_session_id!( data )
0
+ return data unless @stable_session_id
0
+ ( data ||= {} ).merge( inject_stable_session_id!( data ) )
0
+ def inject_stable_session_id!( data )
0
+ if data.respond_to?(:key?) && !data.key?( :session_id )
0
+ { :session_id => CGI::Session.generate_unique_id }
0
# Read the session data cookie.
0
@session.cgi.cookies[@cookie_options['name']].first