Rails 4真实性令牌 - 标题和表单隐藏输入?

Jak*_*ake 6 ruby forms ruby-on-rails csrf authenticity-token

我试图在Rails中获得全页面缓存,但是我对CSRF有一个很大的障碍 - 或许只是我对它的理解.我目前有一个form_authenticity_token存储在一个cookie中的字符串,JS可以访问并重写头标记.

我在生成的HTML中有两个地方找到了令牌:

1)在头部

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

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

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

如上所述,这些哈希值彼此不同(在未启用缓存的开发模式中).他们为什么不同?为什么我可以删除头元标记并单独保留表单输入并允许请求?然而,当我删除表单输入标记并保留标题时,请求被拒绝了?

实际上这意味着头部标签是无用的,不是吗?我可以将表单输入标记重写为我的cookie中的值,就像我对标题标记所做的那样,但由于它们彼此不同,我对于最终结果可能意味着什么,特别是涉及到整页缓存时要谨慎.

Application Controller包含:

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
Run Code Online (Sandbox Code Playgroud)

Jak*_*ake 2

浏览另一个问题让我找到了答案。简而言之,Rails 通过自动将 CSRF 令牌插入到 ajax 请求中来帮助 jQuery 用户。它在元标记中查找它。

因此,在提交 POST 请求时将 CSRF 令牌放在表单中非常有用,而将其放在 header 中则可以节省 ajax 请求的时间/精力/错误。

也许两者都包含它也很好,因为您可能想在没有表单的情况下执行 ajax 请求。如果存在表单并且 javascript 被禁用,则将其放在标头中不会给任何人带来任何好处,因为它不会包含在 POST 请求中。

至于为什么它们不同,我只能猜测这与生成时的算法有关......但这既不在这里也不在那里,因为这两个令牌都可以工作。