【问题标题】:Storing an encrypted cookie with Rails使用 Rails 存储加密的 cookie
【发布时间】:2012-03-11 00:28:34
【问题描述】:

我需要在 Rails 的 cookie 中存储一小段数据(少于 10 个字符),并且我需要它是安全的。我不希望任何人能够读取该数据或注入他们自己的数据(因为这会使应用程序面临多种攻击)。我认为加密 cookie 的内容是可行的方法(我也应该签名吗?)。最好的方法是什么?

现在我正在这样做,这看起来很安全,但是对于比我更了解安全的人来说,很多事情看起来很安全,然后发现它并不真正安全。

我是这样保存秘密的:

encryptor = ActiveSupport::MessageEncryptor.new(Example::Application.config.secret_token)
cookies[:secret] = {
  :value => encryptor.encrypt(secret),
  :domain => "example.com",
  :secure => !(Rails.env.test? || Rails.env.development?)
}

然后我是这样读的:

encryptor = ActiveSupport::MessageEncryptor.new(Example::Application.config.secret_token)
secret = encryptor.decrypt(cookies[:secret])

这样安全吗?有更好的方法吗?

更新:我知道 Rails 的 session 以及它的安全性,通过签署 cookie 和可选地存储 session 服务器端的内容,我确实使用 session 是什么为了。但我的问题是关于存储 cookie,这是我在会话中不想要的一条信息,但我仍然需要它是安全的。

【问题讨论】:

  • 出于兴趣,为什么需要将其存储在 cookie 中而不是服务器端,因为它在定义上更安全?
  • @russell 好吧,你需要在浏览器中存储一些东西,对吧?否则你将无法再次识别它。无论是实际数据还是表上记录的 id,这都是关于数据大小和其他考虑的偏好和必要性问题。我存储的已经是表中记录的 id。我可以创建另一个表,但在这种情况下似乎很浪费。
  • 我添加了一个答案,因为我认为将默认会话存储更改为使用数据库将为您提供所需的安全性,而在创建表等方面的开销很小。
  • @Russell 我不想使用会话。我的会话是针对每个域 (blah.example.com) 而这段数据是针对整个系统 (.example.com),因此设置它时的域选项。

标签: ruby-on-rails security cookies encryption


【解决方案1】:
  • 设置安全 cookie

    cookies.signed[:secret] = {
     :value => "foo bar",
     :domain => "example.com",
     :secure => !(Rails.env.test? || Rails.env.development?)
    }
    
  • 访问 cookie

    cookies.signed[:secret] # returns "foo bar"
    

cookie 使用ActionController::Base.cookie_verifier_secret 签名。您可以在初始化文件中设置cookie_verifier_secret

【讨论】:

  • 我不想使用会话。我的会话是针对每个域 (blah.example.com) 而这段数据是针对整个系统 (.example.com),因此设置它时的域选项。
  • 更新答案看看。
  • 使用 .signed 设置的 Cookie 也需要使用 .signed 访问。所以你的第二个代码块应该是cookies.signed[:secret]
【解决方案2】:

正如 KandadaBoggu 所说,看起来您想要的是一个会话变量,而会话变量默认情况下是加密的并存储在 cookie 中。但是,如果您查看 config/initializers/session_store.rb 的内容,您会发现类似以下内容:

 # Be sure to restart your server when you modify this file.
 MyRailsApp::Application.config.session_store :cookie_store, :key => '_my_rails_app_session'

 # Use the database for sessions instead of the cookie-based default,
 # which shouldn't be used to store highly confidential information
 # (create the session table with "rails generate session_migration")
 # MyRailsApp::Application.config.session_store :active_record_store

这向我建议您应该将数据库用于会话,而不是基于 cookie 的默认值,后者不应用于存储高度机密的信息。预先准备好的迁移使一切都非常容易设置,因此这样做的开销很小,一旦完成,如果您需要在以后添加一条新的秘密信息,开销基本上为零!

【讨论】:

  • 我不想使用会话。我的会话是针对每个域 (blah.example.com) 而这段数据是针对整个系统 (.example.com),因此设置它时的域选项。
【解决方案3】:

我重新发布JacobM 的答案,他删除了,因为这是正确的答案,并为我指明了正确的方向。如果他取消删除,我会删除这个并选择他作为最佳答案。

首先,如果你使用encrypt_and_verify 而不是encrypt 它会 为您签署 cookie。

但是,在安全性方面,我总是更喜欢依靠 已经公开审查过的解决方案,而不是我自己的。 一个例子是encrypted-cookies gem

【讨论】:

  • 我很好奇你为什么不使用签名的cookies?(在Rails 3.x 中默认支持)
  • @KandadaBoggu encrypt_and_verify 或 encrypted-cookies gem(1.0 后)处理的 cookie 已签名,但也已加密。如果这段数据被泄露,那也不会那么严重,但我宁愿不去想它,只是通过加密来保证它的安全,因此对用户来说是不透明的。
猜你喜欢
  • 1970-01-01
  • 2011-07-04
  • 2015-01-15
  • 1970-01-01
  • 2015-06-12
  • 1970-01-01
  • 2015-09-16
  • 2010-11-11
  • 1970-01-01
相关资源
最近更新 更多