【问题标题】:How can I make cookies secure (https-only) by default in rails?默认情况下,如何在 Rails 中使 cookie 安全(仅限 https)?
【发布时间】:2011-04-15 23:23:13
【问题描述】:

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

cookies[:foo] = "bar"

并指定“安全”(仅限 https)标志如下:

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

:secure 默认为假。如何让 cookie 在应用程序范围内默认安全?

这是在 Rails 2.3.8 上

【问题讨论】:

    标签: ruby-on-rails ssl cookies https ruby-on-rails-5


    【解决方案1】:

    ActionController/ActionDispatch 无需猴子补丁,force_ssl 有副作用(例如当behind an ELB 时)。

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

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

    【讨论】:

    • 这是正确的答案(已验证这在 Rails 4.2.7.1 中有效)。为了方便测试,设置secure: true,然后您可以验证cookie是否正确生成。然后可以改回Rails.env.production?
    • 看起来这只会影响会话cookie。询问者要求将安全作为所有 cookie 的默认设置。 @david-cain 能否验证该解决方案是否适用于所有 cookie?
    【解决方案2】:

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

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

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

    如果您想默认保护 Rails 应用程序中的所有 cookie,您可以使用 secure_headers gem。只需将 secure_headers gem 添加到您的 Gemfile 中,bundle install gem 并使用以下内容创建一个 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
    

    【讨论】:

      【解决方案3】:

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

      # 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
      

      Here是same的视频教程。

      【讨论】:

        【解决方案4】:

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

        【讨论】:

        • secure_cookies gem。
        【解决方案5】:
        # session only available over HTTPS
        ActionController::Base.session_options[:secure] = true
        

        【讨论】:

        • 这是 rails 4 的新功能吗?
        • 我不知道。但是,在 Rails 4 中它可以工作。您也可以在您的 Rails 版本中检查此属性。
        • 这仅用于会话 cookie,对吗?一般不用于 cookie?
        • 它在 Rails 4.1 中不起作用:undefined method 'session_options' for ActionController::Base:Class (NoMethodError)
        • 这个放在哪里?
        【解决方案6】:

        从 rails 3.1 开始,根据the rails security guide,您可以在application.rb 中简单地设置以下内容:

        config.force_ssl = true
        

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

        【讨论】:

        • 起初这让我很困惑:config.force_ssl主要 目的是只允许 rails 应用程序通过 SSL 工作,但它在 cookie 上启用 secure 标志。在设置此配置之前,请确保您对它的其余效果没问题:stackoverflow.com/questions/15676596/…
        【解决方案7】:

        感谢@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
        

        你怎么看?

        【讨论】:

        • John,我们在 Rails 应用程序中的哪个位置放置了上面的类?
        • 太棒了。谢谢。还有一件事,我的开发环境 - 使用 webrick - 当我在 environment.rb 中将安全标志设置为 true 时,我无法通过我的登录屏幕 - 我注意到响应中有来自应用程序的设置 cookie。知道会发生什么吗?
        • 如果您在 cookie 上将安全标志设置为 true,则不会为非 https 请求发送 cookie。您在开发环境中使用 https 吗?
        • 我确实在我的 cookie 上将安全标志设置为 true(通过 ActionController::Base.session)。我用 ssl 设置了 apache httpd,它在我的开发环境中转发到 WebRick 并且仍然得到相同的行为
        • 对于在 Rails 3.2.x 上尝试此功能的任何人,我相信 set_cookie 已被重构为 ActionDispatch::Response 所以猴子补丁应该可以工作。
        【解决方案8】:

        快速而肮脏的解决方案:我认为可以通过修改动作包 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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-02-06
          • 1970-01-01
          • 2017-08-07
          • 2012-07-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多