2016-06-03 7 views
1

Ich versuche, einen Service-Worker-Endpunkt in meiner Datenbank zu registrieren, aber wenn ich meine Post-Daten mit Fetch senden die App einen Fehler melden.Rails Kann nicht überprüfen, CSRF-Token Authentizität AJAX mit X-CSRF-TOKEN-Header

Ich möchte die csrf Verifikation behalten. Siehst du etwas falsch?

  var ready; 

      ready = function(){ 
       if ('serviceWorker' in navigator) { 
       console.log('Service Worker is supported'); 
       navigator.serviceWorker.register('/service-worker.js').then(function(reg) { 

       reg.pushManager.subscribe({ 
        userVisibleOnly: true 
       }).then(function(sub) { 
        console.log('endpoint:', sub.endpoint); 
        console.log(sub); 
        var token = $('meta[name=csrf-token]').attr('content') 
      console.log(token); 

        return fetch('/register_endpoint', { 
        method: 'post', 
        headers: { 
         'Content-type': 'application/json', 
         'X-CSRF-TOKEN': token 
        }, 
        body: JSON.stringify({ 
         endpoint: sub.endpoint, 
         authenticity_token: token 

        }) 
        }); 
       }); 


       }).catch(function(err) { 
       console.log('Erreur -> ', err); 
       }); 
       } 

      }; 



      $(document).ready(ready); 
      $(document).on('page:load',ready); 

dank

Antwort

-1

Statt fetch schlage ich vor, könnte es zu machen wie unten:

$.ajax({ url: '_URL_HERE', 
    type: 'POST', 
    beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))}, 
    data: 'someData=' + someData, 
    success: function(response) { 
    $('#someDiv').html(response); 
    } 
}); 
+0

danke es funktioniert, aber können Sie mir erklären, warum? – lokhi

+0

@lokhi Ich weiß nicht, wie 'fetch' in Ihrem Fall funktioniert, aber' $ ajax' Authentizitätstoken wird tatsächlich in die 'beforeSend' Methode eingefügt. BeforeSend: Dieses Ereignis, das vor dem Start einer Ajax-Anforderung ausgelöst wird, ermöglicht Ihnen, das XMLHttpRequest-Objekt zu ändern (ggf. zusätzliche Header zu setzen). – 7urkm3n

+0

Das Herunterschalten in eine andere Bibliothek ist nicht wirklich eine gute Lösung. Die Antwort von Omar Rayward ist die richtige Antwort auf diese Frage. –

0

Dies ist auch nicht für mich arbeiten, so habe ich außer Kraft setzen diese verified_request? Methode CsrfToken

class ApplicationController < ActionController::Base 
    protect_from_forgery 
    skip_before_action :verify_authenticity_token, if: :verified_request? 

    protected 

    def verified_request? 
     return true if request.get? 
     if respond_to?(:valid_authenticity_token?, true) 
     super || valid_authenticity_token?(session, URI.unescape(request.headers['X-CSRF-TOKEN'] || "")) 
     else 
     super || form_authenticity_token == URI.unescape(request.headers['X-CSRF-TOKEN'] || "") 
     end 
    end 
end 
7

Das Problem ist, dass der Session-Cookie wird nicht gesendet werden, wenn credentials nicht als Option innerhalb fetch angegeben .

credentials hat 3 possible values:

  • omit -> keine Cookies senden Hat
  • same-origin -> Nur Cookies senden, wenn die URL auf dem gleichen Ursprung wie das aufrufende Skript ist
  • include -> Immer sende cookies, auch für crossursprungsrufe

Das sollte also wohl funktionieren:

return fetch('/register_endpoint', { 
method: 'post', 
headers: { 
    'Content-type': 'application/json', 
    'X-CSRF-TOKEN': token 
    }, 
    body: JSON.stringify({endpoint: sub.endpoint}), 
    credentials: 'same-origin' 
}) 

Here weitere informationen über die native fetch api.

+0

Dies ist die richtige Antwort. Der Grund dafür ist, dass das CSRF-Token auch in der Rails-Sitzung gespeichert wird (die standardmäßig Cookies verwendet). Damit die Anforderung gültig ist, muss das CSRF-Token, das im Header übergeben wird, mit dem Wert in der Sitzung übereinstimmen. –

+0

Ich konnte dies nicht zum Funktionieren bringen, weil fetch() alle Kopfzeilenschlüssel klein schreibt. Und rails server kann nicht sagen, dass "x-csrf-token" die Info für "X-CSRF-Token" enthält. –