10

Ich habe ein REST API Backend mit Spring MVC und gesichert mit grundlegenden Auth mit Spring Security.JQuery Crossdomäne grundlegenden Auth Anruf

Ich möchte Cross-Domain-Ajax-Aufruf an die REST-API von Javascript-Clients tun. Ich möchte JSONP nicht verwenden, da ich nicht auf GET-Aufrufe beschränkt sein möchte. Ich benutze CORS und ich habe die richtigen Header auf der Serverseite gesetzt.

Angenommen, meine REST-API befindet sich in der Domäne "localhost: 8087" und mein Client unter "localhost: 8086", was ein domainübergreifender Aufruf ist.

In meinem Javascript-Client, den ich mache Ajax-Aufruf mit jQuery:

<script> 
     $.ajax ({ 
      url: "http://localhost:8087/SpringMVC/users/user1", 
      beforeSend: function (xhr) { xhr.setRequestHeader ("Authorization", "Basic xxxxxxxxxxxx"); }, 
      success: function(val) { console.log(val); alert("success" + val); }, 
      error: function(val) { console.log(val); alert("error" + val); } 
     }); 
</script> 

Mein Problem ist, dass jQuery nicht den Authorization-Header in der HTTP-Anforderung senden, und ich weiß nicht, warum. Ich verstehe das nicht, weil ich es in der beforeSend-Methode mache, also sollte es innerhalb der HTTP-Anfrage sein. Ergebnis: Ich habe einen 401 Fehler.

Wenn ich das Skript aus der gleichen Domäne localhost: 8087, die nicht Cross-Domain mehr ist, habe ich kein Problem.

Wie ist es möglich?

Mein Skript ist nur ein Test. Ich beabsichtige nicht, meinen Benutzernamen/mein Passwort auf der Client-Seite zu setzen. Aber ich möchte testen, wie man Ajax-Aufrufe an eine grundlegende auth-geschützte REST-API ausführt. Ich stelle mir vor, dass ich auf der Serverseite meinen Benutzernamen/mein Passwort senden muss, die REST API sendet mir einen Cookie zurück und ich muss den Benutzernamen/das Passwort für meine nächsten Ajax Aufrufe an die REST API nicht mehr weitergeben. Habe ich recht ?

Ich habe meine REST-API mit Chrome Advanced REST-Client getestet und es funktioniert so. Für die erste Anfrage muss ich den Autorisierungsheader übergeben. Dann ist es nicht nötig. Sollte es auch so mit meinem Javascript Webclient funktionieren? Ich beabsichtige, Node.JS mit Backbone zu benutzen, um es zu bauen.

Vielen Dank.

EDIT2: Scheint wirklich ein CORS-Browser-Problem zu sein. Ich habe die Kopfzeile Access-Control-Allow-Methods für OPTIONS-Methode auf Serverseite hinzugefügt und es funktioniert in Chrome. Ich habe Zugriff auf die JSON-Antwort ohne Fehler mehr. Aber ich muss immer noch den Autorisierungsheader für die nächsten Anfragen verwenden. Wie kann ich jQuery sagen, dass das Cookie gesendet werden soll?

Und wenn ich mit Firefox versuchen, 11, habe ich keinen Zugriff auf die Json Antwort, und ich habe den Fehler:

"NetworkError: 401 Non-Autorisé - http://localhost:8087/SpringMVC/users/user1" 
+0

Sind Sie Base64 Codierung für Ihren Benutzernamen/Passwort? –

+0

Ja, ich lege es xxxxxxxx anstelle des echten Benutzernamens: Passwort. – rico

Antwort

8

Offenbar Chrome und Firefox behandeln Cross Domain ein bisschen anders verlangt. Bevor die domänenübergreifende Anforderung ausgeführt wird, führen sie eine so genannte "Preflight" -Anforderung mit der HTTP-OPTIONS-Methode aus. Der Unterschied zwischen Chrome und Firefox besteht darin, dass Chrome auch den Berechtigungsheader mit den Anmeldeinformationen sendet, Firefox dagegen nicht.

Dann bleibt es ein Spring Security-Konfigurationsproblem. Meine URL/users/* ist für alle HTTP-Methoden einschließlich OPTIONS gesichert. Im Fall von Firefox, da der Berechtigungsheader nicht gesendet wird, ist meine Anfrage nicht autorisiert. Wenn ich meine sichere URL/users/* nur auf die GET-Methode beschränke, funktioniert sie perfekt für Firefox.Also habe ich nur, dass in meinem Spring Security Config hinzufügen musste:

<intercept-url pattern="https://stackoverflow.com/users/*" access="isAuthenticated()" method="GET"/> 

Danach habe ich die Wahl: i andere Methoden hinzufügen kann, um in dem Intercept-url gesichert werden, mit Ausnahme OPTIONS, oder ich kann den HTTP beschränken Methodenaufruf zu GET in meinem Spring MVC-Controller, der sogar meine OPTIONS-Aufrufe nach dem Javadoc behandeln wird. Ich habe die zweite Lösung gewählt. Aber wenn jemand eine Lösung findet, die Firefox dazu zwingt, die Zugangsdaten wie Chrome zu senden, wäre es großartig und ich würde dieses wählen.

2

Eine weitere Option für das Konfigurationsszenario Spring Security präsentiert von rico wäre:

<http ... use-expressions="true"> 
    <intercept-url pattern="https://stackoverflow.com/users/*" access="permitAll" method="OPTIONS"/> 
    <intercept-url pattern="https://stackoverflow.com/users/*" access="isAuthenticated()"/> 
    ... 
</http> 

HTTP OPTIONS-Anforderungen werden immer durch die Authentifizierung übergeben und andere HTTP-Methode nicht.

Beachten Sie, dass das use-expressions XML-Attribut auf true in <http> Element festgelegt ist. Spring Security wird dann erwarten, dass die access Attribute der <intercept-url> Elemente enthalten Frühling EL-Ausdrücken, wie permitAll und IsAuthenticated().