我有正在生产中运行的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实例中

最佳答案

Rails生成的任何表单(例如,使用form_for等,而不是您将<form>放在模板中)都会在必要时将反CSRF令牌添加为隐藏字段。如果您自己编写表单并且不包括CSRF隐藏输入,那么Rails依靠CSRF元标记和JavaScript来工作。因此,如果您编写了自己的表单并且没有包括隐藏字段,并且由于某种原因客户端的JavaScript无法正常工作,则可能会出现此错误。由于“客户端的JavaScript由于某种原因无法工作”子句很难检测和调试,因此我实际上有意删除了我网站上的CSRF元标记。这样,如果我忘了包含隐藏的输入,它将对所有人造成破坏(快速失败),我将立即发现它,并且可以对其进行修复。我建议您也这样做。

话虽如此,我建议您查看这些“访问者”的访问日志。你看到什么奇怪的东西吗?


在提交之前,他们是否立即访问上面带有表单的页面?如果不是,则可能是机器人或实际的,真实的CSRF尝试(这就是要检查的内容,不是吗?:))。
他们是否将表单加载到一个EC2上并最终提交给另一个EC2?如果是这样,您能否关闭一台EC2并查看错误是否消失了?
他们是否以某种方式失去了会议?这可能是您的问题,也可能是他们的问题。

07-24 09:44
查看更多