7

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

我在生成的 HTML 中有两个地方可以找到标记:

1)在头部

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

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

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

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

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

应用程序控制器包含:

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
4

1 回答 1

2

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

因此,在表单中包含 CSRF 令牌对于提交 POST 请求并将其放在头部很有用,这对于节省 ajax 请求的时间/精力/错误很有用。

也许同时拥有它也很好,因为您可能想要在没有表单时执行 ajax 请求。如果有一个表单并且 javascript 被禁用,将它放在标题中不会对任何人有任何好处,因为它不会包含在 POST 请求中。

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

于 2016-06-30T00:25:35.683 回答