我做了一些研究来回答你的问题,这里是结果。
首先,让我们看一下这部分:
<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
方法将令牌作为参数。
token
for 的参数之前是从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 问题的更多信息,请查看此问题。