【问题标题】:How do sessions and cookies work in Rails?会话和 cookie 在 Rails 中是如何工作的?
【发布时间】:2015-05-24 19:54:39
【问题描述】:

我一直在使用 Devise 处理我的 Rails 应用程序的身份验证,但从未真正了解它是如何工作的。因为 Devise 还使用 Rails 上设置的会话存储配置,所以我假设这是关于使用 Rails 处理会话的问题。

基本上,我是一个认证新手。我已经阅读了一些关于身份验证的文章,但大多数文章都涉及对我来说没有多大意义的抽象库(他们谈论引擎、中间件等)。我真的在寻找较低级别的细节。

这是我目前所知道的......

我知道 cookie 和会话。 Cookie 是存储在客户端的字符串,用于跨多个 HTTP 请求维护会话。

这是我对身份验证的基本理解(如果我错了,请纠正我):

  1. 当用户登录时,我们向服务器发送 SSL 加密请求。如果凭证有效,我们会在数据库(或任何其他数据存储)上保存一个名为会话 ID 的随机字符串,作为与用户 ID 关联的有效会话 ID。此会话 ID 会随着用户的每次登录/注销而改变。

  2. 在我们的数据存储中保存该会话 ID 后,我们返回一个响应,要求浏览器设置一个带有会话 ID 的 cookie。这个会话 id 和用户 id 将被发送到域的连续请求,直到它过期。对于每个请求,我们的服务器将检查标头上的会话 ID 并验证该会话 ID 是否对该用户 ID 有效。如果是,则认为该用户已通过身份验证。

这是我的问题:

  1. 我读到默认情况下从 Rails 2 开始,它现在使用 CookieStore(而不是 SessionStore),它使用 SHA512(而不是会话 ID)生成会话哈希,所有这些都存储在 cookie 中,这意味着多个用户 id 可以从字面上具有相同的会话哈希,它会正常工作。在我看来,这是一件非常危险的事情,使用存储在服务器上的单个密钥公开大量哈希,并基于此密钥建立整个身份验证系统。是否存在使用散列而不是存储服务器端会话 ID 的真实世界大型应用程序?

  2. 关于在服务器端存储活动会话 ID 的主题,我还读到您可以切换到使用不同类型的 Rails 会话存储。基于此,我听说过系统将身份验证系统作为服务移出,并改用身份验证令牌。什么是身份验证令牌,它与会话 ID 有何不同?

  3. 似乎我可以一直猜测一个随机字符串(对于散列和服务器端会话)来获取现有会话。有没有办法防止这种情况?使用存储在 cookie 上的更多值是否正常? (例如用户名、真实姓名甚至是用于身份验证的其他哈希)

我知道我问了很多,但我相信这对于像我这样不了解身份验证的人很有用,并且对于打下关于该主题的坚实基础非常有用。

【问题讨论】:

  • 这是一个非常好的问题,Devise 的默默无闻长期以来一直是我们公司采用的障碍。将密切关注这一点。
  • 所产生的哈希不仅仅是由登录用户的属性组成。即您无法生成重复的 SHA1 哈希。

标签: ruby-on-rails session authentication cookies devise


【解决方案1】:

我已经读到默认情况下从 Rails 2 开始,它现在使用 生成会话哈希的 CookieStore(而不是 SessionStore) 使用 SHA512(而不是会话 ID),所有这些都存储在 cookie 这意味着多个用户 id 可以从字面上具有相同的 会话哈希,它会正常工作。在我看来,这是 一个非常危险的事情,暴露大量的哈希 存储在服务器上的单个密钥,并基于您的整个 基于此密钥的身份验证系统。

是的,乍一看似乎很可怕,但我不确定真正的危险是什么。在 Rails 4 中,会话数据使用 PBKBF2 加密,然后用您的会话密钥签名。此签名有助于检测加密会话的内容是否已被篡改,如果检测到篡改,服务器将拒绝该会话。

https://cowbell-labs.com/2013-04-10-decrypt-rails-4-session.html

如果有人获得了会话令牌(用于签署会话 cookie)的访问权,那么与试图冒充错误用户的最终用户相比,您手头上的问题可能要大得多。

是否存在使用散列的真实世界大规模应用程序 而不是存储服务器端会话 ID?

老实说,我不知道这个问题的答案,但我怀疑这是 Rails 的“默认”这一事实意味着有不少网站使用 cookie 会话存储。

关于在服务器端存储活动会话 ID 的主题,我也 阅读您可以切换以使用不同类型的会话存储 导轨。基于此,我听说过系统移动身份验证 系统作为服务输出并使用身份验证令牌。什么是身份验证 令牌以及它与会话 ID 有何不同?

我现在在服务器上执行此操作 - 基本上,当用户进行身份验证时会生成一个随机散列,并且该散列被存储、加密和签名,在 cookie 中。 cookie 哈希是服务器端数据存储(在我的情况下为 Redis,但它可以在关系数据库或内存缓存或任何您喜欢的任何东西中)的键,实际会话数据是存储的服务器端映射到该键。这样一来,客户手中的会话数据就会减少,因为人们可能会对其进行解密和分析,因此通常会更安全一些。

似乎我可以一直猜测一个随机字符串(对于两个散列 和服务器端会话)来获取现有会话。有没有办法 防止这种情况?使用存储在 a 上的更多值是否正常 曲奇饼? (例如用户名、真实姓名甚至是另一个哈希 认证)

是的,您可以这样做,但这需要很长时间。您还需要猜测如何对新篡改的 cookie 数据进行签名,以使其与服务器期望看到的内容相匹配,并且使用相当大的密钥进行签名。

我真的认为除了使用 cookie 来保持身份验证状态之外没有太多替代方案(我想如果您感觉异国情调并且不太关心旧版浏览器支持,HTML5 本地存储会起作用)。

【讨论】:

  • 啊..有道理,忘了它实际上加密了哈希,这使它变得更加困难。我仍然对基于令牌的身份验证与会话 ID 有点困惑。根据您的解释,我猜您指的是基于令牌的身份验证?那么基于令牌和仅使用存储在某处的会话 id 有什么区别(它也映射到会话信息对吗?)
  • 我所说的“会话令牌”是用于签署会话的服务器端“密钥”。对于身份验证,您通常只需在会话本身中存储某种用户 ID,它可以是签名的 cookie,或者使用存储在 cookie 中的会话密钥在服务器端。
猜你喜欢
  • 2010-12-10
  • 2013-01-15
  • 2013-04-28
  • 1970-01-01
  • 1970-01-01
  • 2015-08-23
  • 1970-01-01
  • 2013-01-28
  • 2017-01-08
相关资源
最近更新 更多