Rails 4 个真实性令牌 - 在 header 中和形成隐藏输入?

Rails 4 authenticity token - both in header and form hidden input?

我正试图在 Rails 中获得完整的页面缓存,但我在 CSRF 方面遇到了很大的障碍——或者可能只是我对它的理解。我目前将 form_authenticity_token 字符串存储在 cookie 中,JS 可以使用该 cookie 访问和重写 header 标签。

我在生成的 HTML:

中有两个地方可以找到令牌

1) 在头部

<meta name="csrf-token" content="[hash]">

2) 在表单的隐藏输入元素中

<input type="hidden" name="authenticity_token" value="[different hash]">

如前所述,这些哈希值彼此不同(在未启用缓存的开发模式下)。他们为什么不同?为什么我可以删除head meta标签并保留表单输入并且允许请求​​?然而,当我删除表单输入标签并留下 headers 时,请求被拒绝了吗?

实际上这意味着 head 标签没有用,不是吗?我可以将表单输入标签重写为我的 cookie 中的值,就像我对 header 标签所做的那样,但由于它们彼此不同,我对最终结果可能意味着什么持谨慎态度,尤其是当它出现时到整页缓存。

应用程序控制器包含:

protect_from_forgery with: :exception
before_filter :csrf_cookie

def csrf_cookie
  cookies['authenticity-token'.freeze] = {
    value: form_authenticity_token,
    expires: 1.day.from_now,
    secure: (Rails.env.staging? || Rails.env.production?)
  }
end

在另一个问题上浏览 SO led me to the answer。简而言之,Rails 通过自动将 CSRF 令牌插入 ajax 请求来帮助 jQuery 用户。它在元标记中查找它。

因此,在提交 POST 请求时将 CSRF 令牌放在表单中非常有用,将它放在头部对于 time/effort/mistakes 和 ajax 请求非常有用。

也许将它同时包含在两者中也很好,因为您可能希望在不存在表单时执行 ajax 请求。如果有一个表单并且 javascript 被禁用,将它放在 header 中不会给任何人带来任何好处,因为它不会包含在 POST 请求中。

至于为什么它们不同,我只能猜测它与生成时的算法有关...但这既不存在也不存在,因为两个标记都有效。