"警告:无法验证CSRF令牌真实性"错误 - 使用Devise的CORS和:token_authenticatable

asg*_*eo1 5 ajax ruby-on-rails devise cors

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

我的应用程序可以验证确定,可以使GET请求正常.身份验证使用token_authenticatable.即所有请求附加'?auth_token = whatever'

所以,我的实际问题是,当我尝试执行PUT请求时,我得到一个警告:无法在rails日志中验证CSRF令牌真实性消息以及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
}
Run Code Online (Sandbox Code Playgroud)

然后我将这些令牌存储在我的ajax应用程序中,并ajaxSend在jQuery中使用,设置它以便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
Run Code Online (Sandbox Code Playgroud)

然后,我可以在chrome网络选项卡中看到,每个GET请求auth_token都会发送param,以及X-CSRF-Token标头.

然而,在PUT请求它似乎没有工作.

我的理论是CORS正在填补空白.如果您发出CORS请求,您的浏览器实际上会首先发出一个额外的 OPTIONS请求,以检查您是否有权访问此资源.

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

这可能是问题吗?

我该怎么做才能证明这一点?Chrome似乎没有向我显示网络标签中的OPTIONS请求,以帮助我调试问题.

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

sur*_*h.g 0

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