CSRF令牌与会话中的内容不匹配(Rails 4.1)

Jas*_* FB 7 ruby-on-rails csrf authenticity-token csrf-protection

我们在Rails 4.1应用程序中看到了一个不幸的,可能是基于浏览器的CSRF令牌真实性问题.我们在这里发布它是为了询问社区其他人是否也看到它.

请注意,大多数错误报告工具(如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

Jas*_* FB 4

该问题已被识别并修复。我们的 Rails 4.1 应用程序中未设置缓存控制标头,导致默认标头为

\n\n
Cache-Control: max-age=0, private, must-revalidate\n
Run Code Online (Sandbox Code Playgroud)\n\n

该标头的强度不足以强制浏览器不缓存。因此,登录表单和 JSON 令牌被客户端浏览器 \xe2\x80\x94(尤其是移动客户端 \xe2\x80\x94)缓存,并返回已过期的 session_ids。

\n\n

修理:

\n\n

设置缓存控制和编译指示头,如此

\n\n
Cache-Control:no-cache, no-store, max-age=0, must-revalidate\n
Run Code Online (Sandbox Code Playgroud)\n\n

和

\n\n
Pragma: no-cache\n
Run Code Online (Sandbox Code Playgroud)\n\n

在 Rails 中,将其添加到您的 application_controller.rb 中:

\n\n
before_action :set_cache_headers\ndef set_cache_headers\n  response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate"\n  response.headers["Pragma"] = "no-cache"\n  response.headers["Expires"] = "Mon, 01 Jan 1990 00:00:00 GMT"\nend\n
Run Code Online (Sandbox Code Playgroud)\n\n

它应该对应用程序中的每个操作都是全局的吗?这取决于您,但您肯定希望在任何呈现表单(尤其是登录表单)的控制器上执行此操作,或者对于任何呈现可能过期的 JSON 令牌的页面执行此操作。所以在现代应用程序中,简短的答案是肯定的。

\n\n

如果您明确希望缓存 Rails 应用程序响应\xc2\xa0,您需要弄清楚如何显式使这些嵌入的 CSRF 和 JSON 令牌过期。

\n\n

请注意,该症状在大多数移动客户端上以微妙的发生级别显现。

\n\n
\n\n

我在博客文章中对此进行了探讨,请访问我的博客并考虑在那里发表评论进行讨论: https: //blog.jasonfleetwoodboldt.com/2017/09/03/the-great-rails-cache-lie/

\n

  • 对于其他任何人来说,这是一个可用的答案,值得理解其基础。根据此线程:https://github.com/rails/rails/issues/21948 移动客户端通常会终止选项卡以释放内存,然后这些选项卡显示为打开并可提交,但丢失了与 CSRF 令牌匹配的适当 cookie。完全终止缓存确实有帮助,只要没有缓存的站点性能不会受到影响。 (5认同)