Rails 诸位看看我这样理解 rails 的用户登陆过程是不是正确的

so_zengtao · 2014年05月27日 · 最后由 yiming 回复于 2014年05月28日 · 3526 次阅读

所谓的用户登陆

其实就是在网站的每个页面(也就是 每个控制器 的 每个动作 都能取到 current_user)

然后在浏览器里的 cookies 里面存储的是一个没有加密的 hash_string1

然后在数据库里面存储一个加密的 hash_string2 (加密 hash_string1)

然后每个页面通过 cookies 拿到 hash_string1 然后加密之后找到 user 这个找到的 user 就是 current_user

然后就可以对这个 current_user 进行各种蹂躏了对么 亲们?

不是. rails 常用的 devise 没看过源码不清楚。sorcery 和 @rei 在 campo 里自己写的登录逻辑都是记录 user_id。每次请求会自动用 user_id 查询 user 表。

#1 楼 @saiga devise 应该是存了 user_id 和 token,我也打算改成这样,避免 cookie 泄露之后无法让它失效。

#2 楼 @Rei - - 你的意思是改成我这个样子么 卧槽 你怎么是第一个会员

#3 楼 @so_zengtao 因为你遇到好心的大神了。

#3 楼 @so_zengtao 我打算改成 session 存 user_id 和 token,根据两个值来判断登录用户。

#5 楼 @Rei 我明白你说的是什么 貌似通过 token 可以取到 user 对象的 在 users 表格存一个字段(新手说的不对请指正)

#6 楼 @so_zengtao 用 id 查可以少加一个索引。并且我在 campo 的实现里面没有设 token 字段,而是把 password_digest 再 SHA512 hash 一遍得到一个 token。

#6 楼 @so_zengtao token 只是拿来校验是否过期,当 token + id 给了服务器,服务器会到一张专门记 token 的表查询是否存在,不存在则忽略 id 直接清空 session,反之根据 id 拿到 user 对象

#8 楼 @saiga 我的意思是利用 session 登陆。你的 token 应该指的是移动端没有 session 的 token 把

#7 楼 @Rei 你说的是 ruby-china 么 我去 git 看看

#7 楼 @Rei 原来是 rails 的论坛框架。好人一生平安

#11 楼 @so_zengtao @Reicampo

刚刚接触 Rails,我也不知道比较安全,高效的做法。

Rails Tutorial 里是每次登录后用 url_base64 生成一段 16 位的字符串(两段字符串碰巧相同的几率非常非常小)姑且叫 remember_token。然后对这个 16 位字符串做 hash 存到数据库 users 表的一个字段下(为了查询效率这个字段是做 index 的)。你的 app 把 remember_token 存到用户浏览器的 cookie 里。已经登录的用户每次访问页面时,会尝试拿 remember_token 做 hash 去数据库查询用户。当然,为了避免每次都查浪费效率,做了 ||= 处理

self.current_user ||= User.find_by(remember_token_digest: hashed_remember_token)
  1. 如果 cookie 泄露,攻击者可以自动登录你的账号;
  2. 如果你显式地登出,那么 remember_token 会清除,之前泄露的 remember_token 就失效了;
  3. 一旦服务器数据库泄露,由于 remember_token 是 hash 后存的,那么攻击者是很难逆向出原始 remember_token 的。

#13 楼 @yiming 这个和我的做法差不多

#14 楼 @so_zengtao @Rei 目前在 Campo 的做法,倘若用户数据泄露,那么攻击者很容易通过 id + password_digest 的 hash 来伪造 remember_token 的?!当然,如果数据库泄露,人家也不用这么麻烦是吧。但可以悄悄做一些恶意的事情。

#15 楼 @yiming session 是存在于 cookie 的

#16 楼 @so_zengtao 明白。我指的是攻击者拿到了服务器上的用户数据后可能导致的问题。

#16 楼 @so_zengtao Anyway, 这几个方法对 cookie 泄露几乎是无力的。所以用户还是得注意保护自己的敏感数据。

此外,值得注意的是:既然做 hash,那么请务必不要把 hash 前的原始数据暴露出来。无论这个数据是在你的服务器上还是在用户的设备里。

#13 楼 @yiming 如果数据库存 remember_token_digest,似乎支持不了多设备登录?

当然根据不同应用场合有不同的安全级别,目前我做的应用能拿到数据库就已经没什么可偷了。

可以去看下我最新的一篇 topic,有用户登录和退出,以及简单的基于用户组的权限控制

#19 楼 @Rei 对,另一台设备显式 sign in 就会让原先的 session 失效。你说得没错,需要根据实际应用场景做权衡。BTW, campo 是不错的 Rails app 例子。对我这样的新手很有帮助!希望哪天能给 campo 提交 PR。

so_zengtao 关闭了讨论。 04月17日 20:42
需要 登录 后方可回复, 如果你还没有账号请 注册新账号