首页 文章

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

提问于
浏览
7

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

请注意,大多数错误报告工具(如Honeybadger)会自动禁止 ActionController::InvalidAuthenticityToken ,因此您通常不会在错误报告工具中看到问题,除非您不要忘记查看它 .

这是问题所在,这不是一个发展问题 - 这是一个尚未被诊断出来的 生产环境 问题 .

我们看到的例外是在我们网站正常登录时的ActionController :: InvalidAuthenticityToken . 仔细检查表单发送的 authenticity_token 和会话的 _csrf_token (我们使用active_record_store作为我们的session_store设置), they just don't match . 经过直接检查,我可以断定它们是完全不同的代币,但我不知道为什么 .

这不是一个简单的新手开发人员问题,请不要回答有关如何将CSRF令牌从客户端传递到服务器或如何在我的控制器上跳过伪造保护的基本答案 . 我对这两个答案中的任何一个的任何人都没有兴趣: You don't know what you're talking about and you don't understand the depth and complexity of the issue. 我只对那些能够证实这种情况发生在非微不足道的访问者身上的人们感兴趣(并且奇怪地看起来会影响某些人)浏览器比其他浏览器更频繁 . )

我们广泛地看到这个问题,可能约占我们高流量网站的1-2% . 我只在 生产环境 中看到它,我无法在开发中重现它 .

我在IE 11和Edge浏览器上看到的最多(你会注意到Rails 4.1在IE 11和Edge之前发布),但在Android上的Chrome上也是如此,偶尔也会在移动Safari上发布 .

我们的Cache-control标头设置如下:

Cache-Control: max-age=0, private, must-revalidate

1 回答

  • 2

    这已被确定并修复 . 我们的Rails 4.1应用程序中未设置缓存控制头,导致 Cache-Control: max-age=0, private, must-revalidate 的默认头

    此标头不足以强制浏览器不缓存 . 因此,登录表单和JSON令牌由客户端浏览器缓存 - 特别是移动客户端 - 并返回已过期的session_ids .

    修理:

    设置cache-control和pragma header,就这样

    Cache-Control:no-cache, no-store, max-age=0, must-revalidate

    Pragma: no-cache

    在rails中,将其添加到application_controller.rb:

    before_action :set_cache_headers def set_cache_headers response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate" response.headers["Pragma"] = "no-cache" response.headers["Expires"] = "Mon, 01 Jan 1990 00:00:00 GMT" end

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

    如果您明确希望保持Rails应用程序响应缓存,则需要弄清楚如何嵌入这些CSRF和JSON令牌 .

    请注意,症状表现在主要是移动客户端的微妙发生级别 .

相关问题