Rails 对 Session 有效期的一些疑问

chunyang_guo · 2014年01月09日 · 最后由 chunyang_guo 回复于 2014年01月11日 · 7889 次阅读

我在看 Ruby on Rails Tutorial 的第八章登陆时,看到下面几句:

这几天也查了一下 session 和 cookies 的一些资料,请问下诸位: 默认情况下,session 是存储在 cookies 中的,那么上面图片中为什么说关掉页面就登陆失效?

另外我看了下 RubyChina 的源码,使用的是 devise 这个 Gem,但我现在并不打算使用第三方 Gem,该如何实现 RubyChina 的登陆?选择保持登陆状态跟不选择在实现上最大的区别是什么?

另外听人说 cookies 分两种,磁盘上和内存中的,rails 做这种区分吗?

默认情况下 session 存储在 cookie 中,而且此 cookie 的有效期为“浏览器会话”,意思就是当你关闭浏览器之后,此 cookie 就失效了,可能就是你说的内存中的 cookie 吧

“记住我”这个功能我记得 Rails Tutorial 里有讲吧,大体思路就是用户登陆之后将生成一个随机的 token 放到一个有效期为 N 年的 cookie 里(就是你说的磁盘上的 cookie),并且在数据库中也把这个 token 存一份,然后在 login filter 里比较 cookie 里的这个 token 是否和数据库中存储的 token 相匹配。

rails 中默认的 session 用 cookie 存储

举个例子简单的

如果你的代码中

sessions[:user_id] = 111

那么你的 sessions 就是

{
  :user_id => 111
}

序列化加密后(具体是不是这个方式我没有查看源码)的 sessions 就是XXXXXXXXXX的一串字符

然后把XXXXXXXX这个字符串,通过 http header 的方式发送给浏览器,存为 cookie,以后通信都带着这个 cookie

服务器看到这个 cookie 之后,就会解密然后反序列化,拿到原来的

{
  :user_id => 111
}

这就是大概的流程

short answer

我觉得基本使用记住下面两点就足够了:

  • 如果要存一些关闭浏览器就丢失的数据,采用 session[:key] = value
  • 如果希望存一些重启机器都不会丢失的数据,采用 cookies.premanent[:key] = value

long answer

默认情况下,session 是存储在 cookies 中的,那么上面图片中为什么说关掉页面就登陆失效?

rails 的默认 session 采用 CookieStore/EncryptedCookieStore,所以数据是存在 cookie 中的没错。但是就像 1 楼所言,普通 cookie 的生命周期就是 session,所以理论上如果浏览器关闭,那么普通 cookie 就被删除了。(实际中如果你的 chrome://settings/ 中选择了 on startup: continue where I left off 那么情况就不同了)

选择保持登陆状态跟不选择在实现上最大的区别是什么?

如果咱们把当前登陆用户的 id 存在 session 中(也就是存在普通 cookie 中)那么当浏览器关闭后,用户的登陆状态也就丢失了(理论上)。如果要 保持登陆状态 那就可以用 cookie.permanent 来存储相关信息 example 这样失效期是 20 年。(可以用 chrome->view->devtools->resources->cookies) 来查看。

另外听人说 cookies 分两种,磁盘上和内存中的,rails 做这种区分吗?

rails 的 cookie 应该都是存在硬盘上的(没有 in memory cookie)。可以重启一下机器试试 😄

#3 楼 @happypeter 多谢你的答案,清楚很多了。

我今天做了一下登陆,页面如下: 如果不勾中“记住我”就用 session,打上勾就额外用上 cookies

不过有个地方我纠结了一下,就是 token 如果每次登陆都重新生成,那么这种“记住我”功能仅限于一台机器,另一台打上勾这边的 cookies 就无效了,如果 token 生成一次就不变了,又会不会不太安全?

#4 楼 @chunyang_guo 有道理,安全和方便是一对矛盾。

@lululau @davidqhr 多谢 现在清楚很多了。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号