默认情况下,如何在 Rails 中使 cookie 安全(仅限 https)?
Posted
技术标签:
【中文标题】默认情况下,如何在 Rails 中使 cookie 安全(仅限 https)?【英文标题】:How can I make cookies secure (https-only) by default in rails? 【发布时间】:2011-04-15 23:23:13 【问题描述】:在 Rails 控制器中,我可以这样设置 cookie:
cookies[:foo] = "bar"
并指定“安全”(仅限 https)标志如下:
cookies[:foo, :secure => true] = "bar"
:secure
默认为假。如何让 cookie 在应用程序范围内默认安全?
这是在 Rails 2.3.8 上
【问题讨论】:
【参考方案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 安全。
您还可以添加这些推荐配置并设置httponly
和samesite
选项:
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
标志。在设置此配置之前,请确保您对它的其余效果没问题:***.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
【讨论】:
以上是关于默认情况下,如何在 Rails 中使 cookie 安全(仅限 https)?的主要内容,如果未能解决你的问题,请参考以下文章
Rails 5 和设计:如何在不更改默认策略的情况下禁用基于令牌的策略上的会话
在 Rails 中使 TimeWithZone 对象变得惰性
如何在 Ruby on Rails 迁移中使列唯一并为其编制索引?