CORS を使用して別のドメインに認証する単一ページ アプリがあります。すべてのリクエストは JSON リクエストです。
私のアプリはOKを認証でき、GETリクエストをOKにすることができます。認証は token_authenticatable を使用しています。つまり、すべてのリクエストに「?auth_token=whatever」が追加されます
したがって、私の実際の問題は、PUT リクエストを実行しようとすると、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 アプリに保存し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
次に、クロムネットワークタブで、GETリクエストごとにパラメーターとヘッダーauth_token
が送信されていることを確認できます。X-CSRF-Token
ただし、PUT リクエストでは機能していないようです。
私の理論は、CORS が物事を詰め込んでいるというものです。CORS リクエストを行う場合、ブラウザは実際には最初に追加のOPTIONS リクエストを行い、このリソースにアクセスする権限があることを確認します。
X-CSRF-Tokenヘッダーを渡していないのはOPTIONSリクエストであると思われるため、レールはすぐにレール側のcsrf_tokenを無効にします。その後、jQuery が実際の PUT リクエストを行うと、渡された csrf_token は無効になります。
これが問題でしょうか?
それを証明するにはどうすればよいですか?問題のデバッグに役立つように、Chrome のネットワーク タブに OPTIONS リクエストが表示されないようです。
CSRFをオフにするだけなので、大きな問題ではありません。しかし、なぜそれが機能しないのか知りたいです。