表单上的 Railsauthentity_token 与 csrf 令牌

Posted

技术标签:

【中文标题】表单上的 Railsauthentity_token 与 csrf 令牌【英文标题】:Rails authenticity_token on a form vs csrf token 【发布时间】:2016-12-16 16:40:11 【问题描述】:

在 Rails 4 应用程序的同一页面上,我有一个

在头脑中:

<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="some_token" />

正文以下:

<form action="/someaction" method="post">
<input name="utf8" type="hidden" value="&#x2713;" />
<input type="hidden" name="_method" value="patch" />
<input type="hidden" name="authenticity_token" value="another_token" />

js 调用需要 csrf 令牌。但是为什么form token 和csrf token 不一样呢?提交表单时使用了这两个令牌中的哪一个?

【问题讨论】:

【参考方案1】:

我做了一些研究来回答你的问题,这里是结果。

首先我们来看看这部分:

<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="some_token" />

这部分是由方法csrf_meta_tags生成的。从源码中我们可以看出:

    &lt;meta name="csrf-param" /&gt; 的“content”属性值取自request_forgery_protection_token,默认为:authenticity_token

    &lt;meta name="csrf-token" /&gt; 的“content”属性值取自form_authenticity_token 方法,其中令牌要么取自会话,要么生成。

现在让我们看看这部分:

<input type="hidden" name="authenticity_token" value="another_token" />

从源码我们可以看出:

    此隐藏输入由extra_tags_for_form 方法返回。 在extra_tags_for_form 内部调用token_tag 方法。 token_tag 方法将令牌作为参数。 token_tagtoken 参数之前是从 html_options_for_form 方法中的 form_tag 方法的 options 参数中提取的。

因此,如果您没有手动将options 中的authenticity_token 参数设置为您的自定义令牌,并且不满足导致将token 值设置为false 的条件(将在下面提到),token_tag方法将接收nil 并调用用于创建&lt;meta name="csrf-token" /&gt; 标记的相同form_authenticity_token 方法。顺便说一句,为了填充输入的name属性,它也使用request_forgery_protection_token,当&lt;meta name="csrf-param" /&gt;标签生成发生时使用。

因为这一切都发生在同一个请求中,所以在两种情况下调用form_authenticity_token 方法应该返回相同的结果。

这两个令牌中的哪一个用于表单提交?

在提交表单时将使用来自隐藏输入的令牌。

也可以使用来自&lt;meta /&gt; 的令牌,但前提是满足以下所有conditions(即使token_tag 方法的token 参数设置为false):

    :remote =&gt; true 应在 options 中传递 form_tagembed_authenticity_token_in_remote_forms 配置设置为 false。 authenticity_token 未传入 options

但是为什么form token 和csrf token 不一样呢?

至于这个问题,可能是因为缓存的原因。或者,如果您使用 Turbolinks gem,可能会导致此问题(如果您完全刷新页面并再次比较令牌,则可以检查此问题)。有关 Turbolinks 问题的更多信息,请查看this question。

【讨论】:

Turbolinks +1。我遇到了 InvalidAuthenticityToken 问题,因为页面没有完全重新加载,并且页面中的令牌与 meta 标记中的令牌不同。【参考方案2】:

这可能与另一个问题有关,我在其中留下了答案:

CSRF token error occurs when using turbolinks with ruby on rails

【讨论】:

以上是关于表单上的 Railsauthentity_token 与 csrf 令牌的主要内容,如果未能解决你的问题,请参考以下文章

以表单作为变量访问另一个表单上的对象

更改子表单上的 OrderBy

如何从子表单刷新父表单上的数据网格

整个表单上的 encodeURIComponent() (ajax)

如何使用另一个表单上的打开文件对话框更改表单的背景图像

Bootstrap 4 - 内联表单上的全宽表单字段