“警告:无法验证 CSRF 令牌真实性”错误 - 带有 Devise 和 :token_authenticable 的 CORS

Posted

技术标签:

【中文标题】“警告:无法验证 CSRF 令牌真实性”错误 - 带有 Devise 和 :token_authenticable 的 CORS【英文标题】:"WARNING: Can't verify CSRF token authenticity" error - CORS with Devise and :token_authenticatable 【发布时间】:2012-10-14 03:39:32 【问题描述】:

我有一个使用 CORS 对另一个域进行身份验证的单页应用程序。所有请求都是 JSON 请求。

我的应用程序可以进行身份​​验证,并且可以使 GET 请求正常。身份验证使用 token_authenticable。 IE。所有请求都附加 '?auth_token=whatever'

所以,我的实际问题是,当我尝试执行 PUT 请求时,我在 rails 日志中收到 WARNING: Can't verify CSRF token authority 消息以及 CanCan ::AccessDenied(您无权访问此页面。)例外。

只需将 skip_before_filter :verify_authenticity_token 添加到 rails 控制器即可解决此问题。

因此我只能得出结论,我的 ajax 请求发送的 csrf_token 无效或为空。

我真的不明白这是怎么回事,因为我相信我在每个 ajax 请求中都正确地发送了 X-CSRF-Token 标头。

基本上,我的应用会进行身份验证,然后 Devise 会发回一个 auth_token 和一个 csrf_token:

render :status => 200, :json => 
  :auth_token => @user.authentication_token,
  :csrf_token => form_authenticity_token

然后我将这些令牌存储在我的 ajax 应用程序中,并在 jQuery 中使用 ajaxSend 进行设置,以便 jQuery 在每个请求中传递这些令牌:

initialize: ->
  @bindTo $(document), 'ajaxSend', @appendTokensToRequest

appendTokensToRequest: (event, jqXHR, options) ->
  if not @authToken? then return

  if @csrfToken?
    jqXHR.setRequestHeader 'X-CSRF-Token', @csrfToken

  if options.type is 'POST'
    options.data = options.data + (if options.data.match(/\=/) then '&' else '') +
    $.param auth_token:@authToken
  else
    options.url = options.url + (if options.url.match(/\?/) then '&' else '?') +
    $.param auth_token:@authToken

然后我可以在 chrome 网络选项卡中看到,对于每个 GET 请求,正在发送 auth_token 参数以及 X-CSRF-Token 标头。

在 PUT 请求上,但它似乎不起作用。

我的理论是 CORS 把事情搞砸了。如果您发出 CORS 请求,您的浏览器实际上会首先发出 additional OPTIONS 请求,以检查您是否有权访问此资源。

我怀疑是 OPTIONS 请求没有通过 X-CSRF-Token 标头,因此 rails 立即使 rails 端的 csrf_token 无效。然后当 jQuery 发出实际的 PUT 请求时,它传递的 csrf_token 不再有效。

这可能是问题吗?

我能做些什么来证明这一点? Chrome 似乎没有在网络选项卡中显示 OPTIONS 请求来帮助我调试问题。

这不是一个大问题,因为我可以关闭 CSRF 的东西。但我想知道为什么它不起作用。

【问题讨论】:

【参考方案1】:

我认为您需要处理 OPTIONS 请求,该请求应以允许 CORS 请求的各种标头进行响应,IIRC 它们是 access-control-allow-method、access-control-allow-origin 和 access -控制允许标题。因为 OPTIONS 请求失败,所以 PUT 请求可能没有发生。

【讨论】:

好的,我再次阅读,您的 PUT 请求似乎正在发生。无论如何我都会试试这个。也许 OPTIONS 请求使令牌无效,我个人不确定 Rails。但也许 OPTIONS 响应可以发送新令牌以供以某种方式使用。【参考方案2】:

我刚刚遇到了同样的问题。问题是无法在 CORS 中发送 _session_id cookie。因此,当 Rails 尝试验证令牌时,session[:_csrf_token]null,Rails 在比较之前会生成一个新的。

要解决此问题,您需要在 CORS 中启用 cookie 发送。这是Mozilla Developer Network reference。服务器端和客户端都需要工作才能使其正常工作。

客户 - 请参阅您的客户端技术文档。

服务器 - 在对预检 (HTTP OPTIONS) 调用的响应中,将标头 Access-Control-Allow-Credentials 设置为 true(字符串)。

【讨论】:

【参考方案3】:

在 Rails 中,每个表单提交都需要 CSRF 令牌真实性。 它用于安全地提交表单。 当我们打开我们的应用程序时,CSRF 令牌(每次)将在 rails 中新创建。 如果 CSRF 令牌没有在我们的控制器内部传递,则会显示此警告。 我们需要在所有表单提交中传递这个令牌。

【讨论】:

是的,我知道我需要传递 CSRF 令牌。我确实说过我是以 X-CSRF-Token 标头的方式传递它的。所以我不知道为什么我会收到警告消息。我认为这可能与似乎没有该标头的 OPTIONS 请求有关。

以上是关于“警告:无法验证 CSRF 令牌真实性”错误 - 带有 Devise 和 :token_authenticable 的 CORS的主要内容,如果未能解决你的问题,请参考以下文章

Rails 3.1 - 忽略 CSRF?

远程服务器返回错误: 404错误远程服务器返回错误:500错误 HttpWebResponse远程服务器返回错误:(404500) 错误。

Pig 安装错误:错误 pig.Main:错误 2998:未处理的内部错误

Informix 错误:发生了语法错误。错误代码:-201

我收到一个错误:“MetaMask - RPC 错误:错误:错误:[ethjs-rpc] rpc 错误与有效负载”

错误精灵错误跟踪器错误