Basis- und Digest-Authentifizierung für einen REST-Service mit Spring Security

Basis- und Digestauthentifizierung für einen REST-Service mit Spring Security

1. Überblick

Dieser Artikel beschreibt, wieset up both Basic and Digest Authentication on the same URI structure of a REST API. In einem früheren Artikel haben wir eine andere Methode zum Sichern des REST-Service erörtert -form-based authentication. Daher ist die Standard- und Digest-Authentifizierung sowohl die natürliche als auch die REST-fähigere Alternative.

2. Konfiguration der Basisauthentifizierung

Der Hauptgrund dafür, dass die formularbasierte Authentifizierung für einen RESTful-Service nicht ideal ist, besteht darin, dass Spring Securitymake use of Sessions ausgibt - dies ist natürlich der Status auf dem Server, sodassthe statelessness constraints in REST praktisch ignoriert wird.

Wir beginnen mit der Einrichtung der Standardauthentifizierung. Zuerst entfernen wir den alten benutzerdefinierten Einstiegspunkt und filtern aus dem Sicherheitselement des Haupt<http>:


   

   

Beachten Sie, wie die Unterstützung für die Basisauthentifizierung mit einer einzigen Konfigurationszeile -<http-basic /> - hinzugefügt wurde, die die Erstellung und Verkabelung vonBasicAuthenticationFilter undBasicAuthenticationEntryPoint übernimmt.

2.1. Die staatenlose Einschränkung erfüllen - Sitzungen loswerden

Eine der Hauptbeschränkungen des RESTful-Architekturstils besteht darin, dass die Client-Server-Kommunikation vollständigstateless beträgt, wieoriginal dissertation lautet:

5.1.3 Stateless

Als Nächstes fügen wir der Client-Server-Interaktion eine Einschränkung hinzu: Die Kommunikation muss zustandslos sein, wie im CSS-Stil (Client-Stateless-Server) in Abschnitt 3.4.3 (Abbildung 5-3), sodass jede Anforderung von Client zu Der Server muss alle Informationen enthalten, die zum Verständnis der Anforderung erforderlich sind, und kann keinen auf dem Server gespeicherten Kontext nutzen. Session state is therefore kept entirely on the client.

Das Konzept vonSession auf dem Server hat in Spring Security eine lange Geschichte, und es war bisher schwierig, es vollständig zu entfernen, insbesondere als die Konfiguration mithilfe des Namespace durchgeführt wurde.

Spring Securityaugmentsist jedoch die Namespace-Konfiguration mitnew stateless option für die Sitzungserstellung, wodurch effektiv garantiert wird, dass keine Sitzung von Spring erstellt oder verwendet wird. Mit dieser neuen Option werden alle sitzungsbezogenen Filter aus der Sicherheitsfilterkette entfernt, um sicherzustellen, dass die Authentifizierung für jede Anforderung durchgeführt wird.

3. Konfiguration der Digest-Authentifizierung

Ab der vorherigen Konfiguration werden der Filter und der Einstiegspunkt, die zum Einrichten der Digest-Authentifizierung erforderlich sind, als Beans definiert. Dann überschreiben diedigest entry point die von<http-basic> hinter den Kulissen erstellten. Schließlich werden die benutzerdefiniertendigest filter in die Sicherheitsfilterkette eingeführt, wobei dieafter-Semantik des Sicherheitsnamespace verwendet wird, um sie direkt nach dem Basisauthentifizierungsfilter zu positionieren.


   

   
   



   
   



   
   



   
      
         
         
      
   

Leider enthält der Sicherheitsnamespace keinesupport, um die Digest-Authentifizierung automatisch so zu konfigurieren, wie die Basisauthentifizierung mit<http-basic> konfiguriert werden kann. Aus diesem Grund mussten die erforderlichen Beans definiert und manuell in die Sicherheitskonfiguration eingebunden werden.

4. Unterstützung beider Authentifizierungsprotokolle im selben RESTful-Service

Die Standard- oder Digestauthentifizierung kann in Spring Security problemlos implementiert werden. Es unterstützt beide für denselben RESTful-Webdienst mit denselben URI-Zuordnungen, wodurch die Konfiguration und das Testen des Dienstes auf eine neue Ebene komplexer werden.

4.1. Anonyme Anfrage

Bei Basis- und Digest-Filtern in der Sicherheitskette werdenanonymous request - eine Anforderung, die keine Authentifizierungsdaten enthält (Authorization HTTP-Header) - von Spring Security verarbeitet - die beiden Authentifizierungsfilter findenno credentials und setzt die Ausführung der Filterkette fort. Wenn Sie dann sehen, dass die Anforderung nicht authentifiziert wurde, wird einAccessDeniedException ausgelöst und inExceptionTranslationFilter abgefangen, das den Digest-Einstiegspunkt beginnt und den Client zur Eingabe von Anmeldeinformationen auffordert.

Die Zuständigkeiten sowohl des Basisfilters als auch des Digestfilters sind sehr eng. Sie führen die Sicherheitsfilterkette weiterhin aus, wenn sie den Typ der Authentifizierungsinformationen in der Anforderung nicht identifizieren können. Aus diesem Grund kann Spring Security so flexibel konfiguriert werden, dass mehrere Authentifizierungsprotokolle auf demselben URI unterstützt werden.

Wenn eine Anfrage mit den korrekten Authentifizierungsdaten (entweder Basic oder Digest) gestellt wird, wird dieses Protokoll zu Recht verwendet. Bei einer anonymen Anforderung wird der Client jedoch nur zur Eingabe der Digest-Authentifizierungsdaten aufgefordert. Dies liegt daran, dass der Digest-Einstiegspunkt als Haupt- und Einzeleinstiegspunkt der Spring Security-Kette konfiguriert ist. als solchedigest authentication can be considered the default.

4.2. Anfrage mit Authentifizierungsdaten

Einrequest with credentials für die Basisauthentifizierung wird durch denAuthorization-Header identifiziert, der mit dem Präfix“Basic” beginnt. Bei der Verarbeitung einer solchen Anforderung werden die Anmeldeinformationen im Basisauthentifizierungsfilter dekodiert und die Anforderung wird autorisiert. In ähnlicher Weise verwendet eine Anforderung mit Anmeldeinformationen für die Digest-Authentifizierung das Präfix“Digest” für den HeaderAuthorization.

5. Testen beider Szenarien

Die Tests verbrauchen den REST-Service, indem sie nach der Authentifizierung mit Basic oder Digest eine neue Ressource erstellen:

@Test
public void givenAuthenticatedByBasicAuth_whenAResourceIsCreated_then201IsReceived(){
   // Given
   // When
   Response response = given()
    .auth().preemptive().basic( ADMIN_USERNAME, ADMIN_PASSWORD )
    .contentType( HttpConstants.MIME_JSON ).body( new Foo( randomAlphabetic( 6 ) ) )
    .post( paths.getFooURL() );

   // Then
   assertThat( response.getStatusCode(), is( 201 ) );
}
@Test
public void givenAuthenticatedByDigestAuth_whenAResourceIsCreated_then201IsReceived(){
   // Given
   // When
   Response response = given()
    .auth().digest( ADMIN_USERNAME, ADMIN_PASSWORD )
    .contentType( HttpConstants.MIME_JSON ).body( new Foo( randomAlphabetic( 6 ) ) )
    .post( paths.getFooURL() );

   // Then
   assertThat( response.getStatusCode(), is( 201 ) );
}

Beachten Sie, dass der Test mit der Basisauthentifizierung der Anforderungpreemptively Anmeldeinformationen hinzufügt, unabhängig davon, ob der Server eine Authentifizierung angefordert hat oder nicht. Damit soll sichergestellt werden, dass der Server den Client nicht nach Anmeldeinformationen fragen muss, da in diesem Fall Digest-Anmeldeinformationen angefordert werden müssen, da dies die Standardeinstellung ist.

6. Fazit

Dieser Artikel befasste sich mit der Konfiguration und Implementierung der Standard- und der Digestauthentifizierung für einen RESTful-Dienst, wobei hauptsächlich die Unterstützung von Spring Security-Namespaces sowie einige neue Funktionen im Framework verwendet wurden.