class Merb::CookieSession
If you have more than 4K of session data or don't want your data to be visible to the user, pick another session store.
CookieOverflow is raised if you attempt to store more than 4K of data. TamperedWithCookie is raised if the data integrity check fails.
A message digest is included with the cookie to ensure data integrity: a user cannot alter session data without knowing the secret key included in the hash.
To use Cookie Sessions, set in config/merb.yml
:session_secret_key - your secret digest key :session_store - cookie
Constants
- DIGEST
- MAX
Cookies can typically store 4096 bytes.
Attributes
:api: private
Public Class Methods
Generates a new session ID and creates a new session.
Returns¶ ↑
- SessionContainer
-
The new session.
:api: private
# File lib/merb-core/dispatch/session/cookie.rb, line 46 def generate self.new(Merb::SessionMixin.rand_uuid, "", Merb::Request._session_secret_key) end
Parameters¶ ↑
- session_id<String>
-
A unique identifier for this session.
- cookie<String>
-
The raw cookie data.
- secret<String>
-
A session secret.
Raises¶ ↑
- ArgumentError
-
blank or insufficiently long secret.
:api: private
# File lib/merb-core/dispatch/session/cookie.rb, line 78 def initialize(session_id, cookie, secret) super session_id if secret.blank? || secret.length < 16 msg = "You must specify a session_secret_key in your init file, and it must be at least 16 characters" Merb.logger.warn(msg) raise ArgumentError, msg end @secret = secret self.update(unmarshal(cookie)) end
Set up a new session on request: make it available on request instance.
Parameters¶ ↑
- request<Merb::Request>
-
The Merb::Request that came in from Rack.
Returns¶ ↑
- SessionContainer
-
a SessionContainer. If no sessions were found,
a new SessionContainer will be generated.
:api: private
# File lib/merb-core/dispatch/session/cookie.rb, line 60 def setup(request) session = self.new(Merb::SessionMixin.rand_uuid, request.session_cookie_value, request._session_secret_key) session._original_session_data = session.to_cookie request.session = session end
Public Instance Methods
Teardown and/or persist the current session.
If @_destroy is true, clear out the session completely, including removal of the session cookie itself.
Parameters¶ ↑
- request<Merb::Request>
-
request object created from Rack environment.
:api: private
# File lib/merb-core/dispatch/session/cookie.rb, line 98 def finalize(request) if @_destroy request.destroy_session_cookie elsif _original_session_data != (new_session_data = self.to_cookie) request.set_session_cookie_value(new_session_data) end end
Regenerate the session_id.
:api: private
# File lib/merb-core/dispatch/session/cookie.rb, line 109 def regenerate self.session_id = Merb::SessionMixin.rand_uuid end
Protected Instance Methods
Private Instance Methods
Securely compare two digests using a constant time algorithm. This avoids leaking information about the calculated HMAC
Based on code by Michael Koziarski <michael@koziarski.com> github.com/rails/rails/commit/674f780d59a5a7ec0301755d43a7b277a3ad2978
Parameters¶ ↑
- a, b<~to_s>
-
digests to compare.
Returns¶ ↑
- Boolean
-
Do the digests validate?
# File lib/merb-core/dispatch/session/cookie.rb, line 163 def secure_compare(a, b) if a.length == b.length # unpack to forty characters. # needed for 1.8 and 1.9 compat a_bytes = a.unpack('C*') b_bytes = b.unpack('C*') result = 0 for i in 0..(a_bytes.length - 1) result |= a_bytes[i] ^ b_bytes[i] end result == 0 else false end end
Unmarshal cookie data to a hash and verify its integrity.
Parameters¶ ↑
- cookie<~to_s>
-
The cookie to unmarshal.
Raises¶ ↑
- TamperedWithCookie
-
The digests don't match.
Returns¶ ↑
- Hash
-
The stored session data.
:api: private
# File lib/merb-core/dispatch/session/cookie.rb, line 194 def unmarshal(cookie) if cookie.blank? {} else data, digest = Merb::Parse.unescape(cookie).split('--') return {} if data.blank? || digest.blank? unless secure_compare(generate_digest(data), digest) clear unless Merb::Config[:ignore_tampered_cookies] raise TamperedWithCookie, "Maybe the site's session_secret_key has changed?" end end unserialize(data) end end