在 Guides 看到 http://guides.rubyonrails.org/security.html
If the security token doesn’t match what was expected, the session will be reset.
我觉得这也会导致一种攻击啊,session 被重置不就 logout 了么,每次被发个站外请求就被 logout 也不行啊
可以记录 csrf 的 referrer 来提醒用户该网页有问题... airbrake 的异常统计里也能看到哪个站在使坏或者被注入了...
另外重置的是 session 不是 cookie, 如果有"记住我"的设置的话一般会写到 cookie 中而不是 session 中,所以登出的用户只包含没点选"记住我"的那些...
csrf 这个处理方式是凝聚了无数经验的结果...
有跨站的需要就 protect_from_forgery except: [...]
呗。或者对 API 调用整个关掉 csrf 验证。
跑题:csrf 还有各种坑在里面,例如浏览器会缓存页面,如果打开一个登录页面,关闭浏览器再打开浏览器,session 失效,session 里的 csrf token 就和页面上的不一致了,但登录是能成功的。因为 csrf 失效只是清空了 session, 然后登录的话不用验证 session 里的 user id 的,所以还能正常登录,而且这样是没有危险的...
替 @Guest (原 hooopo) 转推: “错误的 csrf token 会重置 session 是为了防穷举爆破啦..“ ,好吧,现在我同意 hooopo 了,有谁愿意进一步讨论么?
Rails 4 貌似不太一样了:
但具体什么区别没细看。
HTTP Header
Cookie: session-id=xxxxxxxx
数据库里的 Session
{csrf-token: "zzzzzzzzzzzzzzzzzz", user-id: 12345}
重置 session 不就啥都没有了...
#24 楼 @bhuztez 嗯我说得太粗略了。其实和 session 的实现相关,rails 里 session 默认是整个 base64 或者加密了加上签名存 cookie 里的,然后 cookie 中的这个 session 项的生命期是没设的,所以关闭浏览器就没了。session 用数据库或者内存存储的话处理会不太一样.
但是实现 remember me 的话,往往是加上一个 expire 比较长的 cookie (那么 cookie 就变成 session=...;remember_me=...;expires=...
了), 关闭浏览器也还存在,清空 session 的动作是不消除其它 cookie 的,这种情况基本没影响...
但如果像 ruby-china 这样,把 session 项也设置上生命期来记住用户登录状态,重置 session 确实什么都没了。
rails 里 session 默认是整个 base64 或者加密了加上签名存 cookie 里的
这个地方是先将 session Marshal dump 然后再 Base64
但是实现 remember me 的话,往往是加上一个 expire 比较长的 cookie (那么 cookie 就变成 session=...;remember_me=...;expires=... 了), 关闭浏览器也还存在,清空 session 的动作是不消除其它 cookie 的,这种情况基本没影响...
这里如果 session 被删除了,即使 cookie 还在也会登出了,因为在应用层的 filter 如果找不到 session 中用于标识用户的信息,会验证失败吧。除非把这些东西都放在 cookie 中,每次取也从 cookie 中取,那 session 没了也没什么影响。
3.2
def handle_unverified_request
reset_session
end
4.0
def handle_unverified_request
request = @controller.request
request.session = NullSessionHash.new(request.env)
request.env['action_dispatch.request.flash_hash'] = nil
request.env['rack.session.options'] = { skip: true }
request.env['action_dispatch.cookies'] = NullCookieJar.build(request)
end
我贴出来 大家鉴赏吧