如何防止Rails用户意外地认证为错误的用户?

具体来说,我编写了一个Rails应用程序,其中我使用默认(在Rails 2.3.5中) CookieStore会话存储,我发现了一个奇怪的问题。

我和其他几个人一直在使用该网站几个星期,我们每个人都有一个基于用户名和密码的登录(每个用户注册自己,我将(盐渍和散列)数据存储在数据库中)。 我将用户ID存储在Rails session对象中(因此,在浏览器和服务器之间来回传递的cookie中)。

这里有一个重点:由于这是一个内部网站点,因此我将cookie设置为保持活动长达2周,以避免用户不得不一直登录。

今天我重置数据库,有意擦除所有用户记录(以及所有其他数据)。 一些用户开始再次注册,然后一个用户发现他们第一次去网站,因为擦除他们自动以不同的用户身份登录!

我想我可以看到为什么会发生这种情况:从该用户的浏览器传递到服务器的用户ID现在与我的数据库中的不同用户记录匹配。 我最初的想法是“哦,亲爱的,我没想到!” 但我想的越多,我就意识到这可能是预期的行为。

我意识到我可以将我的Rails应用程序更改为用户ActiveRecordStore但在我这样做之前我想确保我理解这里发生了什么。 具体来说,使用CookieStore会话和让会话保持活跃一段时间的组合真的会造成这样一个巨大的安全漏洞吗? 或者我错过了什么? session_id应该在这里提供更多的安全性吗?

解决此问题的最简单方法是在重置数据库时更改cookie名称。 cookie名称应该在config / initializers / session_store.rb中

 ActionController::Base.session = { :key => '_your_app_session_v2', 

您也可以更改密码,但如果用户使用旧cookie请求网站,则可能会为您的用户带来错误。

此设置中的大安全漏洞不是cookie长度,而是在cookie中设置user_id。 这意味着登录到您网站的任何人都可以通过更改该cookie来以其他人的身份登录! 黑客只需顺序浏览user_id,登录并查看是否有任何他们想要窃取或滥用的内容。

如果要滚动自己的身份validation,请尝试以下操作:在用户表中添加“令牌”字符串字段。 当有人登录时,将此令牌设置为一组随机数字和字母,并将作为cookie传递给用户。 令牌应该是至少32个字符,字母数字,大写和小写。

现在,当用户转到某个页面时,他们的帐户会被该哈希而不是他们的user_id查找。 值是哈希难以猜测,并且永远不会重复。 重置数据库时,实际上重复了user_id,导致人们彼此登录。

UPDATE

@shingara是对的,因为cookie存储已经处理了安全部分,我的错误。 因此,user_id mixup是一次性的,因为您重置了数据库。 除非您再次重置数据库,否则这不是您在生产环境中遇到的问题。 如果有可能重置,那么仍然按照我的推荐创建令牌。 否则,你很好。

只有当您有2个具有相同user_id的不同用户时才会到达案例。 因此,如果您将user_id定义为unique,则无法实现。

另一种情况,您可以在会话中添加一个用户使用唯一键的哈希。 当您检查会话时,您将获得user_id并检查user_token是否相同。 如果不是,则用户未被授权。

谢谢你的所有回复。 他们都以某种方式回答了我的问题:是的,我的设置(我擦除用户后没有设置新的会话密钥)会产生安全漏洞。

很多Rails教程提倡这种设置,但没有提到你需要的只是将你的cookie作为另一个用户进行完全认证。

总而言之,我问了这个问题,因为我找不到任何讨论CookieStore会话+长cookie生命周期危险的CookieStore ,而且我发现这令人惊讶,以为我可能会遗漏一些明显的东西。

我遇到了类似的问题并使用类似于mdesantis关于管理Rails秘密令牌的评论的代码片段来解决它