Fixieren von 401s mit CORS Preflights und Spring Security

1. Übersicht

In diesem kurzen Tutorial erfahren Sie, wie Sie den Fehler "Antwort für Preflight hat ungültigen HTTP-Statuscode 401" beheben, der in Anwendungen auftreten kann, die die Kommunikation zwischen verschiedenen Ursprüngen unterstützen und Spring Security verwenden.

Zuerst werden wir sehen, was originensübergreifende Anfragen sind, und dann werden wir ein problematisches Beispiel beheben.

2. Ursprungsübergreifende Anfragen

Kurz gesagt, Cross-Origin-Anforderungen sind HTTP-Anforderungen, bei denen der Ursprung und das Ziel der Anforderung unterschiedlich sind. Dies ist beispielsweise der Fall, wenn eine Webanwendung von einer Domäne aus bereitgestellt wird und der Browser eine AJAX-Anforderung an einen Server in einer anderen Domäne sendet.

Um Ursprungsübergreifende Anforderungen zu verwalten, muss der Server einen bestimmten Mechanismus aktivieren, der als CORS oder Cross-Origin Resource Sharing bezeichnet wird.

Der erste Schritt in CORS ist eine OPTIONS- Anforderung, um festzustellen, ob das Ziel der Anforderung dies unterstützt. Dies wird als Vorfluganforderung bezeichnet.

Der Server kann dann auf die Anfrage vor dem Flug mit einer Sammlung von Headern antworten:

  • Access-Control-Allow-Origin : Definiert, welche Ursprünge Zugriff auf die Ressource haben dürfen. Ein '*' steht für einen beliebigen Ursprung
  • Access-Control-Allow-Methods : Gibt die zulässigen HTTP-Methoden für originensübergreifende Anforderungen an
  • Access-Control-Allow-Headers : Gibt die zulässigen Anforderungsheader für originensübergreifende Anforderungen an
  • Access-Control-Max-Age : Definiert die Ablaufzeit des Ergebnisses der zwischengespeicherten Preflight-Anforderung

Wenn die Anforderung vor dem Flug die in diesen Antwortheadern ermittelten Bedingungen nicht erfüllt, führt die tatsächliche Folgeanforderung zu Fehlern im Zusammenhang mit der Cross-Origin-Anforderung.

Es ist einfach, unserem Spring-Service CORS-Unterstützung hinzuzufügen. Bei falscher Konfiguration schlägt diese Anforderung vor dem Flug jedoch immer mit einem 401 fehl.

3. Erstellen einer CORS-fähigen REST-API

Um das Problem zu simulieren, erstellen wir zunächst eine einfache REST-API, die Ursprungsübergreifende Anforderungen unterstützt:

@RestController @CrossOrigin("//localhost:4200") public class ResourceController { @GetMapping("/user") public String user(Principal principal) { return principal.getName(); } }

Die Annotation @CrossOrigin stellt sicher, dass auf unsere APIs nur von dem in ihrem Argument angegebenen Ursprung aus zugegriffen werden kann.

4. Sichern unserer REST-API

Lassen Sie uns jetzt unsere REST-API mit Spring Security sichern:

@EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() .httpBasic(); } }

In dieser Konfigurationsklasse haben wir die Autorisierung für alle eingehenden Anforderungen erzwungen. Infolgedessen werden alle Anforderungen ohne gültiges Autorisierungstoken abgelehnt.

5. Vorabanfrage stellen

Nachdem wir unsere REST-API erstellt haben, versuchen wir eine Anfrage vor dem Flug mit curl :

curl -v -H "Access-Control-Request-Method: GET" -H "Origin: //localhost:4200" -X OPTIONS //localhost:8080/user ... < HTTP/1.1 401 ... < WWW-Authenticate: Basic realm="Realm" ... < Vary: Origin < Vary: Access-Control-Request-Method < Vary: Access-Control-Request-Headers < Access-Control-Allow-Origin: //localhost:4200 < Access-Control-Allow-Methods: POST < Access-Control-Allow-Credentials: true < Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH ...

An der Ausgabe dieses Befehls können wir erkennen, dass die Anforderung mit einem 401 abgelehnt wurde.

Da dies ein Curl- Befehl ist, wird in der Ausgabe der Fehler "Antwort für Preflight hat ungültigen HTTP-Statuscode 401" nicht angezeigt.

Wir können diesen genauen Fehler jedoch reproduzieren, indem wir eine Front-End-Anwendung erstellen, die unsere REST-API aus einer anderen Domäne verwendet und in einem Browser ausführt.

6. Die Lösung

Wir haben die Preflight-Anforderungen in unserer Spring Security-Konfiguration nicht explizit von der Autorisierung ausgeschlossen . Denken Sie daran, dass Spring Security standardmäßig alle Endpunkte schützt.

Infolgedessen erwartet unsere API auch in der OPTIONS-Anforderung ein Autorisierungstoken.

Spring bietet eine sofort einsatzbereite Lösung, um OPTIONS-Anforderungen von Autorisierungsprüfungen auszuschließen:

@EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { // ... http.cors(); } }

Die cors () -Methode fügt den von Spring bereitgestellten CorsFilter zum Anwendungskontext hinzu, wodurch die Berechtigungsprüfungen für OPTIONS-Anforderungen umgangen werden.

Jetzt können wir unsere Anwendung erneut testen und feststellen, dass sie funktioniert.

7. Fazit

In diesem kurzen Artikel haben wir gelernt, wie der Fehler "Antwort für Preflight hat ungültigen HTTP-Statuscode 401" behoben wird, der mit Spring Security- und Cross-Origin-Anforderungen verknüpft ist.

Beachten Sie, dass im Beispiel der Client und die API auf verschiedenen Domänen oder Ports ausgeführt werden sollten, um das Problem neu zu erstellen. Beispielsweise können wir den Standardhostnamen dem Client und die Computer-IP-Adresse unserer REST-API zuordnen, wenn sie auf einem lokalen Computer ausgeführt werden.

Wie immer finden Sie das in diesem Tutorial gezeigte Beispiel auf Github.