如何在 Rails 中处理带有陈旧 CSRF 真实性令牌的页面

Posted

技术标签:

【中文标题】如何在 Rails 中处理带有陈旧 CSRF 真实性令牌的页面【英文标题】:How to handle pages with stale CSRF authenticity tokens in Rails 【发布时间】:2012-05-14 07:54:12 【问题描述】:

在我们的 Rails 应用程序中,用户通常会同时打开多个浏览器选项卡数小时或数天。当用户在其中一个选项卡中注销然后重新登录(或会话到期并创建新会话)时,就会出现问题。

这会导致所有其他选项卡上的 CSRF 真实性令牌无效。如果他们尝试在这些选项卡上提交任何表单或发出任何 ajax 请求而不刷新,他们将收到错误消息(实际上会被注销,因为这是通过错误的真实性令牌时 Rails 的默认行为)。

这种行为显然是不可取的。我想知道人们如何优雅地处理用户打开您网站的窗口但真实性令牌已过期的情况。

我不想做的只是将他们重定向到登录页面,因为那样他们可能会丢失他们的工作,例如他们一直在写一篇很长的博客文章或其他东西。

想到的解决方案是使用一些 javascript 来轮询服务器以检查真实性令牌是否已更改,或轮询用户的 cookie 以检查会话是否已更改。我从来没有听说过有人这样做,所以我想看看社区是怎么想的。

【问题讨论】:

【参考方案1】:

首先:登录/注销/登录不会导致出现新的 csrf-token。它仍然会保存在用户的 cookie 中。下次它通过同一个浏览器登录时,它会得到相同的令牌。

在最新版本的 Rails 中,在令牌不正确的情况下不会引发错误:Rails 所做的一切——只是在将会话传递给控制器​​之前重置会话。

所以,更新你的 Rails,你会少一点痛苦。

【讨论】:

你是对的,登录/注销不会导致新的 csrf 令牌生成。看起来像是回到绘图板上找出这些无效令牌错误的来源。 如果不能升级 Rails 怎么办?【参考方案2】:

你确定你说的是 CSRF 令牌而不是会话令牌吗?在 CSRF 令牌不匹配时重定向到登录根本没有任何意义。你只是告诉用户重复他试图做的任何事情。 (在传统的 Web 应用程序中,这通常在提交表单时出现;您可以将 CSRF 不匹配视为验证错误,并再次显示表单,保留所有字段值,并要求用户重新提交。在更多 AJAX - 重型应用程序,您可以在响应中使用某种通用 CSRF 标志,如果已设置,请用户再次执行他所做的任何事情(按下按钮等),甚至可以在不打扰用户的情况下自动化整个事情。

【讨论】:

您能否详细说明如何将 csrf 不匹配视为验证错误?一般来说,有没有一种 Rails 的方式来做到这一点? 我对 Rails 不是很熟悉,但this 似乎是一种方法。

以上是关于如何在 Rails 中处理带有陈旧 CSRF 真实性令牌的页面的主要内容,如果未能解决你的问题,请参考以下文章

Rails 3:无法验证 CSRF 令牌的真实性

无法验证 CSRF 令牌的真实性 Rails/React

Rails用户登录错误:无法验证CSRF令牌的真实性

无法验证 CSRF 令牌真实性 Rails 4.1

Angular + Rails:POST 请求 422/CSRF 错误

基本 .ajax 发布到 rails 3.2.2 脚手架,生成“警告:无法验证 CSRF 令牌真实性”