【发布时间】:2023-04-11 02:38:01
【问题描述】:
我有一个使用 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 的东西。但我想知道为什么它不起作用。
【问题讨论】:
标签: ruby-on-rails ajax devise cors