Class Merb::CookieSession
In: merb-core/lib/merb-core/dispatch/session/cookie.rb
Parent: SessionContainer

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

Methods

Classes and Modules

Class Merb::CookieSession::CookieOverflow
Class Merb::CookieSession::TamperedWithCookie

Constants

MAX = 4096   Cookies can typically store 4096 bytes.
DIGEST = OpenSSL::Digest::Digest.new('SHA1')

Attributes

_original_session_data  [RW]  :api: private

Public Class methods

Generates a new session ID and creates a new session.

Returns

SessionContainer:The new session.

:api: private

[Source]

    # File merb-core/lib/merb-core/dispatch/session/cookie.rb, line 46
46:       def generate
47:         self.new(Merb::SessionMixin.rand_uuid, "", Merb::Request._session_secret_key)
48:       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

[Source]

    # File merb-core/lib/merb-core/dispatch/session/cookie.rb, line 78
78:     def initialize(session_id, cookie, secret)
79:       super session_id
80:       if secret.blank? || secret.length < 16
81:         msg = "You must specify a session_secret_key in your init file, and it must be at least 16 characters"
82:         Merb.logger.warn(msg)
83:         raise ArgumentError, msg
84:       end
85:       @secret = secret
86:       self.update(unmarshal(cookie))
87:     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

[Source]

    # File merb-core/lib/merb-core/dispatch/session/cookie.rb, line 60
60:       def setup(request)
61:         session = self.new(Merb::SessionMixin.rand_uuid,
62:           request.session_cookie_value, request._session_secret_key)
63:         session._original_session_data = session.to_cookie
64:         request.session = session
65:       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

[Source]

     # File merb-core/lib/merb-core/dispatch/session/cookie.rb, line 98
 98:     def finalize(request)
 99:       if @_destroy
100:         request.destroy_session_cookie
101:       elsif _original_session_data != (new_session_data = self.to_cookie)
102:         request.set_session_cookie_value(new_session_data)
103:       end
104:     end

Regenerate the session_id.

:api: private

[Source]

     # File merb-core/lib/merb-core/dispatch/session/cookie.rb, line 109
109:     def regenerate
110:       self.session_id = Merb::SessionMixin.rand_uuid
111:     end

Create the raw cookie string; includes an HMAC keyed message digest.

Returns

String:Cookie value.

Raises

CookieOverflow:More than 4K of data put into session.

Notes

Session data is converted to a Hash first, since a container might choose to marshal it, which would make it persist attributes like ‘needs_new_cookie’, which it shouldn‘t.

:api: private

[Source]

     # File merb-core/lib/merb-core/dispatch/session/cookie.rb, line 127
127:     def to_cookie
128:       unless self.empty?
129:         data = self.serialize
130:         value = Merb::Parse.escape "#{data}--#{generate_digest(data)}"
131:         if value.size > MAX
132:           msg = "Cookies have limit of 4K. Session contents: #{data.inspect}"
133:           Merb.logger.error!(msg)
134:           raise CookieOverflow, msg
135:         end
136:         value
137:       end
138:     end

Protected Instance methods

Serialize current session data as a Hash. Uses Base64 encoding for integrity.

Returns

String:Base64 encoded dump of the session hash.

:api: private

[Source]

     # File merb-core/lib/merb-core/dispatch/session/cookie.rb, line 189
189:     def serialize
190:       Base64.encode64(Marshal.dump(self.to_hash)).chop
191:     end

Unserialize the raw cookie data to a Hash

Returns

Hash:the session hash Base64 decoded from the data dump.

:api: private

[Source]

     # File merb-core/lib/merb-core/dispatch/session/cookie.rb, line 199
199:     def unserialize(data)
200:       Marshal.load(Base64.decode64(data)) rescue {}
201:     end

Private Instance methods

Generate the HMAC keyed message digest. Uses SHA1.

Returns

String:an HMAC digest of the cookie data.

:api: private

[Source]

     # File merb-core/lib/merb-core/dispatch/session/cookie.rb, line 148
148:     def generate_digest(data)
149:       OpenSSL::HMAC.hexdigest(DIGEST, @secret, data)
150:     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

[Source]

     # File merb-core/lib/merb-core/dispatch/session/cookie.rb, line 164
164:     def unmarshal(cookie)
165:       if cookie.blank?
166:         {}
167:       else
168:         data, digest = Merb::Parse.unescape(cookie).split('--')
169:         return {} if data.blank? || digest.blank?
170:         unless digest == generate_digest(data)
171:           clear
172:           unless Merb::Config[:ignore_tampered_cookies]
173:             raise TamperedWithCookie, "Maybe the site's session_secret_key has changed?"
174:           end
175:         end
176:         unserialize(data)
177:       end
178:     end

[Validate]