Rails WARNING: Can't verify CSRF token authenticity

shatle · 2013年07月31日 · 最后由 yuki 回复于 2015年02月02日 · 11027 次阅读

最近出现个问题,之前是没有的,「如题」。

之前部署时已经参照 http://stackoverflow.com/questions/7203304/warning-cant-verify-csrf-token-authenticity-rails 做了。

之前运行是没有这一问题的,我用 firefox 查看:

CSRF 已经在 headers 中加上了。

PUT 出现错误,其它非 GET 操作应该也有这一问题。


其实,在我每次更新,从而重新部署时,开始那段时间是没有问题的。但是,过了一段时间(我也不知道大概多久,两三小时/半天?),就会有这一问题。多次出现这一问题了,才不得不在这里占个位!

谢谢!

请查看源码 actionpack/lib/action_controller/metal/request_forgery_protection.rb

session[:_csrf_token] 和 HTTP header 里的 X-CSRF-Token ,要一致,你看看是否一致呢?

@zhangyuan session[:_csrf_token] 在 appxx_controller 看是空的,HTTP headers 的 X-CSRF-Token 是有值的

session[:_csrf_token] 是否有手动赋予值?

def form_authenticity_token
  session[:_csrf_token] ||= SecureRandom.base64(32)
end

此源码中的代码会不会自动赋值?

你如果在 view 里掉用过 csrf_meta_tags ,那么就会设置。这个方法内部调用了 form_authenticity_token 方法,其实就是这个方法设置的。

在 development 环境下,如果 csrf_token 验证失败,默认会重置 session。

form_tagform_for 等 helper 方法,也会设置这个 session[:_csrf_token]

@zhangyuan 我的请求是 ajax 的

不会要加在参数里面吧?请求的 headers 这个起的作用是????

#5 楼 @shatle 如果用 ajax,按照 rails 默认的方式,应该:

  1. 引入 jquery_ujs.js 这个 javascript 文件
  2. 在页面上调用 csrf_meta_tags

由于 csrf_token 校验不过,那么可能重置 session。所以要查看 session[:_csrf_token] ,那么要在可能重置之前,来查看 session 的内容。

如果 session 按照 rails 的默认方式,保存在 cookie 里,那么你可以把 session 解码出来,看看对不对。

@zhangyuan  #7 以上说的两个点,我应该都有的

GET

session[:_csrf_token]::: BIlGiqMH+OZYHJhYeTFdjYwsbbFMNlz9sv0A1u3HyQw=
request.headers[X-CSRF-Token]:: 7p1neymbxlIRlwOlyhpsLWJLQYEMOwEvYH/iDuA6MhU=
current_user 1 >>> shatle
Completed 200 OK in 3ms (Views: 0.2ms)

PUT

session[:_csrf_token]::: 
request.headers[X-CSRF-Token]:: 7p1neymbxlIRlwOlyhpsLWJLQYEMOwEvYH/iDuA6MhU=
current_user 1 >>> 

session 是在 cookie 的吗?

@zhangyuan

同一帐户在不同浏览器出现一样的request.headers[X-CSRF-Token], 会不会有问题?

#11 楼 @shatle 理论上没问题。但是,理论上不应该一样吧? 你没保存在 cookie 里是吧?

怎么请求 request.headers[X-CSRF-Token] 它的值都是一样的。

session 是保存在数据库中的,使用了 https://github.com/brianhempel/mongo_session_store

request.headers[X-CSRF-Token] 和 页面上的 meta tag 一样。

比如

<meta content="authenticity_token" name="csrf-param" />
<meta content="3sYnxLVEbfdbWUrpMosTeRFS56QvcThA+XNscU916Ck=" name="csrf-token" />

你是不是把这个缓存了?

@zhangyuan 啊!cache?!!!!!

@zhangyuan 应该就是这一原因了,我自己 cache 太多了,谢谢了!!!!

mark 搞了好久

#7 楼 @zhangyuan 我简直想亲你,哈哈哈

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