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

Posted

技术标签:

【中文标题】Rails 4 真实性令牌 - 在标题和表单隐藏输入中?【英文标题】:Rails 4 authenticity token - both in header and form hidden input? 【发布时间】:2016-08-19 11:15:14 【问题描述】:

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

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

1) 在头脑中

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

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

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

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

实际上这意味着 head 标签是无用的,不是吗?我可以将表单输入标签重写为我的 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

【问题讨论】:

【参考方案1】:

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

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

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

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

【讨论】:

以上是关于Rails 4 真实性令牌 - 在标题和表单隐藏输入中?的主要内容,如果未能解决你的问题,请参考以下文章

如何在rails中处理来自应用程序控制器的无效真实性令牌json请求

无法验证 CSRF 令牌真实性 Rails 4.1

即使设置了标头,也无法验证 CSRF 令牌的真实性 Rails 4 Ajax

Rails 3 真实性令牌

无法在 Rails 中验证 CSRF 令牌的真实性

无法验证 CSRF 令牌的真实性 Rails/React