我在生产中运行Rails4应用程序,我的访问者偶尔运行到ActionController :: InvalidAuthenticityToken错误,我无法重现。我从各种表格收到每日2-4次通知,背后没有明确的逻辑。我收到的报告显示,表单提交的authenticity_token与会话中保存的不同。这怎么可能?我设法自己遇到问题几次,但是无法重现,表单的所有突然的authenticity_token都与会话中存储的不同,并且出现了InvalidAuthenticityToken。
任何想法从哪里开始寻找?
例如:
Request:
-------------------------------
* URL : https://domain/signin
* HTTP Method: POST
* IP address : 113.96.xx.xx
* Parameters : {"utf8"=>"✓", "authenticity_token"=>"MOh9JDE1AZ0CbIw/M33vfhjRShwzI6oqMhi8lk+n7OE=", "email"=>"xxxx@xxx", "password"=>"[FILTERED]", "commit"=>"Sign In", "controller"=>"clients", "action"=>"signin", "locale"=>"en"}
-------------------------------
Session:
-------------------------------
* session id: [FILTERED]
* data: {"_csrf_token"=>"QazCSVGeZlxEh83XTM+f5PkC/zopwCF96yV4duRats0="}
更新:想要添加我通过两个负载均衡的AWS EC2实例服务页面,并在Redis ElastiCache实例中存储会话
答案 0 :(得分:16)
由Rails生成的任何表单(即form_for
等),而不是将<form>
放入模板中)都会在必要时将反CSRF令牌添加为隐藏字段。如果您自己编写表单并且未包含CSRF隐藏输入,那么Rails依赖于CSRF元标记和JavaScript来实现工作。因此,如果您编写了自己的表单并且未包含隐藏字段,并且如果客户端的JavaScript因任何原因无效,则可能会出现此错误。因为“客户端的JavaScript不能用于任何原因”是一个很难检测和调试的子句,所以我实际上故意删除了我网站上的CSRF元标记。这样,如果我忘记包含隐藏的输入,它将为每个人打破(快速失败),我会立即发现它,我可以解决它。我建议你也这样做。
话虽如此,我建议您查看这些“访问者”的访问日志。你觉得奇怪吗?
答案 1 :(得分:4)
由于rails使用JavaScript将authenticity_token
附加到rails表单,因此我会检查您是否存在基于导致此heisenbug的动态内容的运行时JS错误。如果我们要破坏整个application.js文件的JS错误,那么您的表单将无效。这可能吗?
答案 2 :(得分:1)
登录时发生这种情况会让我怀疑您的退出时可能出现问题,从而为退出并立即重新登机的用户触发问题。
注销通常会破坏当前用户会话并将其替换为新会话,从而使CSRF标记无效。通常这不是问题,因为用户被重定向到包含新CSRF标记的另一个页面。
如果
,我可以看到这是一个问题答案 3 :(得分:1)
我遇到了同样的麻烦。 服务器:nginx +乘客
<强> nginx.conf:强>
http {
...
expires 90d;
...
server {
server_name domain1.com
...
}
server {
server_name domain2.com
...
}
server {
server_name domain_3_with_rails.com
...
}
}
指令中的问题“到期90d;” 浏览器本地缓存的页面,包含表单和authenticity_token。
解决方案:为rails domains添加"expires 0d;"
:
<强> nginx.conf:强>
http {
...
expires 90d;
...
server {
server_name domain1.com
...
}
server {
server_name domain2.com
...
}
server {
server_name domain_3_with_rails.com
expires 0d;
...
}
}
之后,请务必重启Nginx。
对于那些拥有apache的人:apache肯定对nginx有类似的声明“expires”
答案 4 :(得分:1)
我现在遇到同样的问题。我一直在四处寻找,我注意到如果我关闭cookie(阻止域可以使用cookie),每次我做POST
时都会遇到ActionController :: InvalidAuthenticityToken。
因此用户已启用JS但不允许使用Cookie。
AFAIK Rails中的反CSRF令牌作为会话cookie服务器端发送,然后因为无法设置cookie而失败。