Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source
Show
Ignore:
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/actionpack/lib/action_controller/session/cookie_store.rb

    r6294 r6296  
    11require 'cgi' 
    22require 'cgi/session' 
    3 require 'base64'        # to make marshaled data HTTP header friendly 
    4 require 'digest/sha2'   # to generate the data integrity hash 
     3require 'base64'        # to convert Marshal.dump to ASCII 
     4require 'openssl'       # to generate the HMAC message digest 
    55 
    66# This cookie-based session store is the Rails default. Sessions typically 
     
    99# alternatives. 
    1010# 
    11 # A secure hash is included with the cookie to ensure data integrity: 
    12 # a user cannot alter his user_id without knowing the secret key included in 
    13 # the hash. New apps are generated with a session :secret option in 
    14 # Application Controller. Set your own for old apps you're upgrading. 
    15 # Note that changing the secret invalidates all existing sessions! 
    16 # 
    1711# If you have more than 4K of session data or don't want your data to be 
    1812# visible to the user, pick another session store. 
     
    2014# CookieOverflow is raised if you attempt to store more than 4K of data. 
    2115# TamperedWithCookie is raised if the data integrity check fails. 
     16# 
     17# A message digest is included with the cookie to ensure data integrity: 
     18# a user cannot alter his user_id without knowing the secret key included in 
     19# the hash. New apps are generated with a pregenerated secret in 
     20# config/environment.rb. Set your own for old apps you're upgrading. 
     21# 
     22# Session options: 
     23#   :secret   An application-wide key string or block returning a string 
     24#             called per generated digest. The block is called with the 
     25#             CGI::Session instance as an argument. 
     26# 
     27#             Example:  :secret => '449fe2e7daee471bffae2fd8dc02313d' 
     28#                       :secret => Proc.new { User.current_user.secret_key } 
     29# 
     30#   :digest   The message digest algorithm used to verify session integrity 
     31#             defaults to 'SHA1' but may be any digest provided by OpenSSL, 
     32#             such as 'MD5', 'RIPEMD160', 'SHA256', etc. 
     33# 
     34# Note that changing digest or secret invalidates all existing sessions! 
    2235class CGI::Session::CookieStore 
    2336  # Cookies can typically store 4096 bytes. 
     
    3447    # The secret option is required. 
    3548    if options['secret'].blank? 
    36       raise ArgumentError, 'A secret is required to generate an integrity hash for cookie session data. Use session :secret => "some secret phrase" in ApplicationController.
     49      raise ArgumentError, 'A secret is required to generate an integrity hash for cookie session data. Use config.action_controller.session = { :secret => "some secret phrase" } in config/environment.rb
    3750    end 
    3851 
    3952    # Keep the session and its secret on hand so we can read and write cookies. 
    4053    @session, @secret = session, options['secret'] 
     54 
     55    # Message digest defaults to SHA1. 
     56    @digest = options['digest'] || 'SHA1' 
    4157 
    4258    # Default cookie options derived from session settings. 
     
    98114    end 
    99115 
    100     # Generate the inline SHA512 message digest. Larger (128 bytes) than SHA256 
    101     # (64 bytes) or RMD160 (40 bytes), but small relative to the 4096 byte 
    102     # max cookie size. 
     116    # Generate the HMAC keyed message digest. Uses SHA1 by default. 
    103117    def generate_digest(data) 
    104       Digest::SHA512.hexdigest "#{data}#{@secret}" 
     118      key = @secret.respond_to?(:call) ? @secret.call(@session) : @secret 
     119      OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new(@digest), key, data) 
    105120    end 
    106121