How can I make cookies secure (https-only) by defa

2020-05-21 08:55发布

问题:

In a Rails controller, I can set a cookie like this:

cookies[:foo] = "bar"

And specify that the "secure" (https-only) flag be on like this:

cookies[:foo, :secure => true] = "bar"

:secure is false by default. How can I have cookies be secure by default, application-wide?

This is on Rails 2.3.8

回答1:

There's no need to monkeypatch ActionController/ActionDispatch, and force_ssl has side effects (e.g. when behind an ELB).

The most straightforward way to achieve secure cookies is to modify config/initializers/session_store.rb:

MyApp::Application.config.session_store :cookie_store, key: '_my_app_session',
                                                       secure: Rails.env.production?


回答2:

starting with rails 3.1, according to the rails security guide, you can simply set the following in your application.rb:

config.force_ssl = true

this forces the cookie to be sent over https only (and I assume everything else, too).



回答3:

Thanks @knx, you sent me down the right path. Here's the monkeypatch I came up with, which seems to be working:

class ActionController::Response
  def set_cookie_with_security(key, value)
    value = { :value => value } if Hash != value.class
    value[:secure] = true
    set_cookie_without_security(key, value)
  end
  alias_method_chain :set_cookie, :security
end

What do you think?



回答4:

To force SSL and enable the secure cookie for an entire Ruby on Rails application, enable force_ssl in your environment file such as production.rb.

# config/environments/production.rb
config.force_ssl = true

If you need to support HTTP and HTTPS traffic with your Ruby on Rails application, set the secure cookie flag for your application so that session cookies are ONLY sent over HTTPS.

The consequence is you can no longer maintain session state over HTTP, but you at least protect yourself from session hijacking attacks.

# config/initializers/session_store.rb
# set secure: true, optionally only do this for certain Rails environments (e.g., Staging / Production
Rails.application.config.session_store :cookie_store, key: '_testapp_session', secure: true

Here is the video tutorial of same.



回答5:

Quick and dirty solution: i think it is possible by modifying []= method in action pack cookies module (actionpack/lib/action_controller/cookies.rb)

from:

    def []=(name, options)
      if options.is_a?(Hash)
        options = options.inject({}) { |options, pair| options[pair.first.to_s] = pair.last; options }
        options["name"] = name.to_s
      else
        options = { "name" => name.to_s, "value" => options }
      end

      set_cookie(options)
    end

to:

    def []=(name, options)
      if options.is_a?(Hash)
        options.merge!({:secure => true})
        options = options.inject({}) { |options, pair| options[pair.first.to_s] = pair.last; options }
        options["name"] = name.to_s
      else
        options = { "name" => name.to_s, "value" => options }
      end

      set_cookie(options)
    end


回答6:

# session only available over HTTPS
ActionController::Base.session_options[:secure] = true


回答7:

You should look at the rack-ssl-enforcer gem. I was just looking for a clean answer to this and it solves the problem independent of which version of Rails you're on, plus it's extremely configurable.