请注意,大多数错误报告工具(如Honeybadger)会自动禁止ActionController :: InvalidAuthenticityToken,因此您通常不会在错误报告工具中看到此问题,除非您不遗余力地查看它.
这是问题,这不是一个发展问题 – 这是一个尚未被诊断出来的生产问题.
我们看到的例外是在我们网站正常登录时的ActionController :: InvalidAuthenticityToken.仔细检查表单发送的authenticity_token和会话的_csrf_token(我们使用active_record_store作为我们的session_store设置),它们只是不匹配.经过直接检查,我可以断定它们是完全不同的代币,但我不知道为什么.
这不是一个简单的新手开发人员问题,请不要回答有关如何将CSRF令牌从客户端传递到服务器或如何在我的控制器上跳过伪造保护的基本答案.我不感兴趣听到任何一个有这两个答案的人:你不知道你在说什么,你不明白问题的深度和复杂性.我只对收听流量较高的网站的人有兴趣,他们可以确认这种情况发生在非无关紧要的访问者身上(奇怪的是,似乎比其他浏览器更频繁地影响某些浏览器.)
我们广泛地看到这个问题,可能约占我们高流量网站的1-2%.我只在生产中看到它,我无法在开发中重现它.
我在IE 11和Edge浏览器上看到的最多(你会注意到Rails 4.1在IE 11和Edge之前发布),但也在Android上的Chrome上,偶尔也在移动Safari上.
我们的Cache-control标头设置如下:
Cache-Control:max-age = 0,private,must-revalidate
解决方法
Cache-Control:max-age = 0,must-revalidate
此标头不足以强制浏览器不缓存.因此,登录表单和JSON令牌由客户端浏览器缓存 – 特别是移动客户端 – 并返回已过期的session_ids.
修理:
设置cache-control和pragma header,就这样
Cache-Control:no-cache,no-store,max-age = 0,must-revalidate
和
Pragma:没有缓存
在rails中,将其添加到application_controller.rb:
before_action:set_cache_headers
def set_cache_headers
response.headers [“Cache-Control”] =“no-cache,must-revalidate”
response.headers [“Pragma”] =“no-cache”
response.headers [“Expires”] =“星期一,1990年1月1日00:00:00 GMT”
结束
应用程序中的每个操作都应该是全局的吗?这取决于您,但您肯定希望在呈现表单的任何控制器(尤其是登录表单)或呈现可能过期的JSON令牌的任何页面上执行此操作.所以在现代应用中,简短的回答是肯定的.
如果您明确希望保持Rails应用程序响应缓存,则需要弄清楚如何嵌入这些CSRF和JSON令牌.
请注意,症状表现在主要是移动客户端的微妙发生级别.