Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 7525

Show
Ignore:
Timestamp:
09/21/07 15:05:49 (1 year ago)
Author:
david
Message:

Added support for HTTP Only cookies (works in IE6+ and FF 2.0.5+) as an improvement for XSS attacks (closes #8895) [lifo/Spakman]

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/actionpack/CHANGELOG

    r7523 r7525  
    11*SVN* 
     2 
     3* Added support for HTTP Only cookies (works in IE6+ and FF 2.0.5+) as an improvement for XSS attacks #8895 [lifo/Spakman] 
    24 
    35* Don't warn when a path segment precedes a required segment. Closes #9615. [Nicholas Seckar] 
  • trunk/actionpack/lib/action_controller/cgi_ext/cookie.rb

    r6733 r7525  
    44class CGI #:nodoc: 
    55  class Cookie < DelegateClass(Array) 
     6    attr_accessor :name, :value, :path, :domain, :expires 
     7    attr_reader :secure, :http_only 
     8 
    69    # Create a new CGI::Cookie object. 
    710    # 
     
    2023    #          false).  Secure cookies are only transmitted to HTTPS 
    2124    #          servers. 
    22     # 
     25    # http_only:: whether this cookie can be accessed by client side scripts (e.g. document.cookie) or only over HTTP  
     26    #             More details: http://msdn2.microsoft.com/en-us/library/system.web.httpcookie.httponly.aspx 
     27    #             Defaults to false. 
    2328    # These keywords correspond to attributes of the cookie object. 
    2429    def initialize(name = '', *value) 
     
    2934        @expires = nil 
    3035        @secure = false 
     36        @http_only = false 
    3137        @path = nil 
    3238      else 
     
    3642        @expires = name['expires'] 
    3743        @secure = name['secure'] || false 
     44        @http_only = name['http_only'] || false 
    3845        @path = name['path'] 
    3946      end 
    4047 
    41       unless @name 
    42         raise ArgumentError, "`name' required" 
    43       end 
     48      raise ArgumentError, "`name' required" unless @name 
    4449 
    4550      # simple support for IE 
     
    5661    end 
    5762 
    58     attr_accessor("name", "value", "path", "domain", "expires") 
    59     attr_reader("secure") 
     63    # Set whether the Cookie is a secure cookie or not. 
     64    def secure=(val) 
     65      @secure = val == true 
     66    end 
    6067 
    61     # Set whether the Cookie is a secure cookie or not. 
    62     # 
    63     # +val+ must be a boolean. 
    64     def secure=(val) 
    65       @secure = val if val == true or val == false 
    66       @secure 
     68    # Set whether the Cookie is an HTTP only cookie or not. 
     69    def http_only=(val) 
     70      @http_only = val == true 
    6771    end 
    6872 
    6973    # Convert the Cookie to its string representation. 
    7074    def to_s 
    71       buf = "" 
     75      buf = '' 
    7276      buf << @name << '=' 
    73  
    74       if @value.kind_of?(String) 
    75         buf << CGI::escape(@value) 
    76       else 
    77         buf << @value.collect{|v| CGI::escape(v) }.join("&") 
    78       end 
    79  
    80       if @domain 
    81         buf << '; domain=' << @domain 
    82       end 
    83  
    84       if @path 
    85         buf << '; path=' << @path 
    86       end 
    87  
    88       if @expires 
    89         buf << '; expires=' << CGI::rfc1123_date(@expires) 
    90       end 
    91  
    92       if @secure == true 
    93         buf << '; secure' 
    94       end 
    95  
    96       buf 
     77      buf << (@value.kind_of?(String) ? CGI::escape(@value) : @value.collect{|v| CGI::escape(v) }.join("&")) 
     78      buf << '; domain=' << @domain if @domain 
     79      buf << '; path=' << @path if @path 
     80      buf << '; expires=' << CGI::rfc1123_date(@expires) if @expires 
     81      buf << '; secure' if @secure 
     82      buf << '; HttpOnly' if @http_only 
    9783    end 
    9884 
  • trunk/actionpack/lib/action_controller/cookies.rb

    r7438 r7525  
    2424  # * <tt>expires</tt> - the time at which this cookie expires, as a +Time+ object. 
    2525  # * <tt>secure</tt> - whether this cookie is a secure cookie or not (default to false). 
    26   #   Secure cookies are only transmitted to HTTPS servers. 
     26  #                     Secure cookies are only transmitted to HTTPS servers. 
     27  # * <tt>http_only</tt> - whether this cookie is accessible via scripting or only HTTP (defaults to false). 
     28   
    2729  module Cookies 
    2830    protected 
  • trunk/actionpack/test/controller/cookie_test.rb

    r7435 r7525  
    3333    end 
    3434 
     35    def authenticate_with_http_only 
     36      cookies["user_name"] = { :value => "david", :http_only => true } 
     37    end 
     38 
    3539    def rescue_action(e)  
    3640      raise unless ActionController::MissingTemplate # No templates here, and we don't care about the output  
     
    5963    get :authenticate_for_fourten_days 
    6064    assert_equal [ CGI::Cookie::new("name" => "user_name", "value" => "david", "expires" => Time.local(2005, 10, 10)) ], @response.headers["cookie"] 
     65  end 
     66 
     67  def test_setting_cookie_with_http_only 
     68    get :authenticate_with_http_only 
     69    assert_equal [ CGI::Cookie::new("name" => "user_name", "value" => "david", "http_only" => true) ], @response.headers["cookie"] 
     70    assert_equal CGI::Cookie::new("name" => "user_name", "value" => "david", "path" => "/", "http_only" => true).to_s, @response.headers["cookie"].to_s 
    6171  end 
    6272