Rails authenticity_token在表单vs csrf标记上

时间:2016-08-10 10:35:13

标签: ruby-on-rails csrf authenticity-token

在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" />

csrf令牌需要js调用。但为什么表单令牌与csrf令牌不同?表单提交中使用了哪两个令牌?

1 个答案:

答案 0 :(得分:2)

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

首先,我们来看看这部分:

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

此部分由方法csrf_meta_tags生成。从源代码中我们可以看到:

  1. <meta name="csrf-param" />的“内容”属性值取自request_forgery_protection_token,默认情况下为:authenticity_token

  2. <meta name="csrf-token" />的“content”属性值取自form_authenticity_token方法,其中令牌可以从会话中获取,也可以生成。

  3. 现在让我们看一下这部分:

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

    从源头我们可以看到:

    1. 此隐藏输入由extra_tags_for_form方法返回。
    2. 内部extra_tags_for_form调用token_tag方法。
    3. token_tag方法将令牌作为参数。
    4. token token_tag的参数以前是从form_tag方法html_options_for_form方法的options参数中提取的。
    5. 因此,如果您未在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)的所有内容都将被满足时:

      1. :remote => true应该在options的{​​{1}}中传递。
      2. form_tag config设置为false。
      3. embed_authenticity_token_in_remote_forms未在authenticity_token传递。
      4.   

        但为什么表单令牌与csrf令牌不同?

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