表单上的 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="✓" />
<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生成的。从源码中我们可以看出:
<meta name="csrf-param" />
的“content”属性值取自request_forgery_protection_token,默认为:authenticity_token
。
<meta name="csrf-token" />
的“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_tag
的 token
参数之前是从 html_options_for_form 方法中的 form_tag 方法的 options
参数中提取的。
因此,如果您没有手动将options
中的authenticity_token
参数设置为您的自定义令牌,并且不满足导致将token
值设置为false 的条件(将在下面提到),token_tag
方法将接收nil
并调用用于创建<meta name="csrf-token" />
标记的相同form_authenticity_token 方法。顺便说一句,为了填充输入的name
属性,它也使用request_forgery_protection_token,当<meta name="csrf-param" />
标签生成发生时使用。
因为这一切都发生在同一个请求中,所以在两种情况下调用form_authenticity_token
方法应该返回相同的结果。
这两个令牌中的哪一个用于表单提交?
在提交表单时将使用来自隐藏输入的令牌。
也可以使用来自<meta />
的令牌,但前提是满足以下所有conditions(即使token_tag
方法的token
参数设置为false):
:remote => true
应在 options
中传递 form_tag
。
embed_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 令牌的主要内容,如果未能解决你的问题,请参考以下文章