我做了一些研究来回答你的问题,这里是结果。
首先,让我们看一下这部分:
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="some_token" />
这部分是由方法csrf_meta_tags生成的。从源代码中我们可以看到:
的“内容”属性值<meta name="csrf-param" />取自request_forgery_protection_token,默认情况下是:authenticity_token。
“内容”属性值<meta name="csrf-token" />取自form_authenticity_token方法,其中令牌要么取自会话,要么生成。
现在让我们看看这部分:
<input type="hidden" name="authenticity_token" value="another_token" />
从源码我们可以看出:
- 这个隐藏的输入由extra_tags_for_form方法返回。
- 内部
extra_tags_for_form调用token_tag方法。
token_tag方法将令牌作为参数。
tokenfor 的参数之前是从html_options_for_form方法中的form_tag方法的参数中token_tag提取的。options
因此,如果您没有手动将authenticity_token参数设置options为自定义令牌并且不满足导致将token值设置为 false 的条件(将在下面提到),token_tag则方法将接收并调用用于标签nil的相同form_authenticity_token<meta name="csrf-token" />方法创造。顺便说一句,对于name输入的填充属性,它还使用request_forgery_protection_token,在<meta name="csrf-param" />标签生成时使用。
并且因为这一切都发生在同一个请求中,form_authenticity_token所以在两种情况下调用方法都应该返回相同的结果。
这两个令牌中的哪一个用于表单提交?
在提交表单时,将使用来自隐藏输入的令牌。
<meta />也可以使用来自的令牌,但前提是满足以下所有条件(使方法token的参数token_tag设置为 false):
:remote => true应该传入options的form_tag。
embed_authenticity_token_in_remote_forms配置设置为假。
authenticity_token没有传入options。
但是为什么form token 和csrf token 不一样呢?
至于这个问题,可能是因为缓存的原因出现了这个问题。或者,如果您使用 Turbolinks gem,可能会导致此问题(如果您完全刷新页面并再次比较令牌,则可以检查此问题)。有关 Turbolinks 问题的更多信息,请查看此问题。