39

在 Rails 控制器中,我可以像这样设置 cookie:

cookies[:foo] = "bar"

并指定“安全”(仅限 https)标志是这样的:

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

:secure默认为假。默认情况下,如何让 cookie 在应用程序范围内保持安全?

这是在 Rails 2.3.8 上

4

8 回答 8

48

无需猴子补丁ActionController/ ActionDispatch,并且force_ssl有副作用(例如,在 ELB 后面时)。

实现安全 cookie 的最直接方法是修改config/initializers/session_store.rb

MyApp::Application.config.session_store( 
  :cookie_store, 
  key: '_my_app_session',
  secure: Rails.env.production?
)
于 2015-07-06T20:33:56.307 回答
19

从 rails 3.1 开始,根据rails security guide,您可以简单地在您的application.rb

config.force_ssl = true

这会强制 cookie 仅通过 https 发送(我也假设其他所有内容)。

于 2013-09-21T11:20:51.410 回答
4

谢谢@knx,你让我走上了正确的道路。这是我想出的猴子补丁,它似乎正在工作:

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

你怎么看?

于 2010-09-23T18:09:26.103 回答
2

要强制 SSL 并为整个 Ruby on Rails 应用程序启用安全 cookie,请在您的环境文件(例如 production.rb)中启用 force_ssl。

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

如果您的 Ruby on Rails 应用程序需要支持 HTTP 和 HTTPS 流量,请为您的应用程序设置安全 cookie 标志,以便会话 cookie 仅通过 HTTPS 发送。

结果是您无法再通过 HTTP 维护会话状态,但您至少可以保护自己免受会话劫持攻击。

# 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

是相同的视频教程。

于 2019-01-02T12:08:58.580 回答
1

快速而肮脏的解决方案:我认为可以通过修改动作包 cookie 模块中的 []= 方法(actionpack/lib/action_controller/cookies.rb)

从:

    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

至:

    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
于 2010-09-23T00:28:04.417 回答
1
# session only available over HTTPS
ActionController::Base.session_options[:secure] = true
于 2013-11-20T04:01:25.153 回答
0

您应该查看 rack-ssl-enforcer gem。我只是在寻找一个干净的答案,它解决了与您使用的 Rails 版本无关的问题,而且它非常可配置。

于 2016-06-17T20:42:07.910 回答
0

您可以按照上述某些答案中的说明执行此操作(使用文件secure中的选项config/initializers/session_store.rb):

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

这只会保护会话 cookie,但其他 cookie 将不安全。

如果您想默认保护 Rails 应用程序中的所有 cookie,可以使用secure_headers gem。只需将secure_headersgem 添加到您的 Gemfile、bundle installgem 并创建一个config/initializers/secure_headers.rb包含以下内容的文件:

SecureHeaders::Configuration.default do |config|
  config.cookies = {
    secure: true, # mark all cookies as "Secure"
  }
end

默认情况下,这将使 Rails 应用程序中的所有 cookie 安全。

您还可以添加这些推荐的配置并设置httponlysamesite选项:

SecureHeaders::Configuration.default do |config|
  config.cookies = {
    secure: true, # mark all cookies as "Secure"
    httponly: true, # mark all cookies as "HttpOnly"
    samesite: {
      lax: true # mark all cookies as SameSite=lax
    }
  }
end
于 2020-08-07T05:21:03.583 回答