“警告:无法validationCSRF令牌真实性”错误 – 使用Devise的CORS和:token_authenticatable

我有一个单页面应用程序使用CORSvalidation到另一个域。 所有请求都是JSON请求。

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

所以,我的实际问题是,当我尝试执行PUT请求时,我得到一个警告:无法在rails日志中validationCSRF令牌真实性消息以及CanCan :: AccessDenied(您无权访问此页面。 )例外。

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

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

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

基本上,我的应用程序validation并且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发送auth_token参数,以及X-CSRF-Token标头。

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

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

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

这可能是问题吗?

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

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

我认为你需要处理OPTIONS请求,它应该响应允许CORS请求的各种头,IIRC它们是access-control-allow-method,access-control-allow-origin和access-control-允许报头。 由于OPTIONS请求失败,因此可能没有发生PUT请求。

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

要解决此问题,您需要在CORS中启用cookie发送。 这是Mozilla开发人员网络参考 。 服务器和客户端都需要工作才能使其工作。

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

服务器 – 在对预检(HTTP OPTIONS)调用的响应中将标头Access-Control-Allow-Credentialstrue (字符串)。

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