在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" />
csrf令牌需要js调用。但为什么表单令牌与csrf令牌不同?表单提交中使用了哪两个令牌?
答案 0 :(得分:2)
我做了一些研究来回答你的问题,这是结果。
首先,我们来看看这部分:
<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" />
的“content”属性值取自form_authenticity_token方法,其中令牌可以从会话中获取,也可以生成。
现在让我们看一下这部分:
<input type="hidden" name="authenticity_token" value="another_token" />
从源头我们可以看到:
extra_tags_for_form
调用token_tag方法。token_tag
方法将令牌作为参数。token
token_tag
的参数以前是从form_tag方法html_options_for_form方法的options
参数中提取的。因此,如果您未在authenticity_token
中手动将options
参数设置为自定义令牌,并且不符合导致将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
方法的token_tag
参数设置为false)的所有内容都将被满足时:
:remote => true
应该在options
的{{1}}中传递。form_tag
config设置为false。embed_authenticity_token_in_remote_forms
未在authenticity_token
传递。但为什么表单令牌与csrf令牌不同?
至于这个问题,可能是因为缓存而出现此问题。或者,可能,如果您使用Turbolinks gem,它可能会导致此问题(如果您完全刷新页面并再次比较令牌,则可以检查此问题)。有关Turbolinks问题的更多信息,请查看this question。