2012-10-24 9 views
5

Ich habe eine App mit einer einzelnen Seite, die sich mit einer anderen Domäne authentifiziert, die CORS verwendet. Alle Anfragen sind JSON-Anfragen."WARNUNG: Fehler bei der CSRF-Token-Authentizität kann nicht überprüft werden - CORS mit Devise und: token_authentifyable

Meine App kann OK authentifizieren und GET-Anforderungen OK machen. Die Authentifizierung verwendet token_authenticatable. I.e. alle Anfragen anhänge

Also, mein eigentliches Problem ist, dass, wenn ich versuche, eine PUT-Anfrage ich eine WARNUNG zu tun bekommen ‚auth_token = was auch immer?‘: Kann CSRF-Token Authentizität nicht überprüfen Nachricht in den Schienen und melden Sie sich als a CanCan :: AccessDenied (Sie sind nicht berechtigt, auf diese Seite zuzugreifen.) Ausnahme.

Das einfache Hinzufügen von skip_before_filter :verify_authenticity_token zum Rails-Controller behebt das Problem.

Daher kann ich nur schließen, dass meine Ajax-Anfragen ein ungültiges oder leeres csrf_token senden.

Ich verstehe nicht wirklich, wie das sein kann, da ich glaube, dass ich den X-CSRF-Token-Header korrekt mit jeder Ajax-Anfrage senden.

Grundsätzlich meine Anwendung authentifiziert und Devise sendet eine auth_token und csrf_token zurück:

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

Ich speichere dann die Token in meiner Ajax-Anwendung, und ajaxSend in jQuery verwenden, ist es so einrichten, geht jQuery diese Token mit jeder Anforderung:

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 

kann ich dann in der Chrom Registerkarte Netzwerk sehen, dass für jeden GET Anfrage des auth_token param gesendet sowie die X-CSRF-Token Header wird.

Auf PUT-Anfragen scheint es jedoch nicht zu funktionieren.

Meine Theorie ist, dass CORS die Dinge stopft. Wenn Sie eine CORS-Anfrage stellen, macht Ihr Browser zunächst eine zusätzliche OPTIONS-Anfrage, um zu überprüfen, ob Sie die Berechtigung zum Zugriff auf diese Ressource haben.

Ich vermute, dass es die OPTIONS-Anfrage ist, die den X-CSRF-Token-Header nicht übergeben wird, so dass Schienen sofort das csrf_token auf dem Schienenende ungültig macht. Wenn jQuery dann die tatsächliche PUT-Anforderung annimmt, ist das von ihm übergebene csrf_token nicht mehr gültig.

Könnte das das Problem sein?

Was kann ich tun, um das zu beweisen? Chrome scheint mir nicht die OPTIONS-Anfragen auf der Registerkarte "Netzwerk" anzuzeigen, damit ich das Problem beheben kann.

Es ist kein großes Problem, weil ich das CSRF-Zeug einfach ausschalten kann. Aber ich würde gerne wissen, warum es nicht funktioniert.

Antwort

0

In Rails jedes Formular Vorlage CSRF Token Authentizität. Sie verwenden, um Formular sicher einzureichen. Das CSRF-Token wird jedes Mal neu erstellt, wenn wir unsere Anwendung öffnen. Wenn das CSRF-Token nicht in unseren Controller gelangt, wird diese WARNUNG angezeigt. Wir müssen dieses Token in allen Formulareinreichungen übergeben.

+0

Ja, ich weiß, dass ich das CSRF-Token übergeben muss. Ich habe gesagt, dass ich es in der Art des X-CSRF-Token-Headers übergebe. Also weiß ich nicht, warum ich dann die WARNING-Nachricht bekommen würde. Ich dachte, es könnte etwas mit der OPTIONS-Anfrage zu tun haben, die diesen Header nicht zu haben schien. – asgeo1

1

Ich denke, Sie müssen die OPTIONS-Anfrage behandeln, die mit den verschiedenen Kopfzeilen reagieren sollte, die die CORS-Anfrage ermöglichen, IIRC sie sind die Zugriffssteuerung-erlauben-Methode, Access-Control-allow-Herkunft und access-control-allow-headers. Da die OPTIONS-Anforderung fehlschlägt, tritt die PUT-Anforderung wahrscheinlich nicht auf.

+0

Ok ich lese wieder es scheint, dass Ihre PUT Anfrage auftritt. Ich würde es trotzdem versuchen. Vielleicht macht die OPTIONS-Anfrage das Token ungültig, ich bin nicht sicher über Rails persönlich. Aber vielleicht könnte die OPTIONS-Antwort das neue Token senden, das irgendwie verwendet werden soll. – jamiebarrow

1

Ich lief gerade in das gleiche Problem. Das Problem ist, dass der Cookie _session_id nicht in CORS gesendet werden kann. Wenn Rails versucht, das Token zu überprüfen, lautet das session[:_csrf_token] dann null, und Rails generiert ein neues vor dem Vergleich.

Um das Problem zu lösen, müssen Sie das Senden von Cookies in CORS aktivieren. Hier ist die Mozilla Developer Network reference. Es ist sowohl auf der Server- als auch auf der Clientseite erforderlich, dass es funktioniert.

Client - Siehe Dokument mit den Clienttechnologien.

Server - Stellen Sie den Header Access-Control-Allow-Credentials zu true (string) in der Antwort auf die Preflight (HTTP OPTIONS) Aufruf.

Verwandte Themen