Standardkennwortcodierer in Spring Security 5

1. Übersicht

In Spring Security 4 war es möglich, Kennwörter mithilfe der speicherinternen Authentifizierung im Klartext zu speichern.

Bei einer umfassenden Überarbeitung des Kennwortverwaltungsprozesses in Version 5 wurde ein sichererer Standardmechanismus zum Codieren und Decodieren von Kennwörtern eingeführt. Wenn Ihre Spring-Anwendung Kennwörter im Klartext speichert, kann ein Upgrade auf Spring Security 5 zu Problemen führen.

In diesem kurzen Tutorial werden wir eines dieser potenziellen Probleme beschreiben und eine Lösung demonstrieren.

2. Federsicherheit 4

Zunächst wird eine Standard-Sicherheitskonfiguration angezeigt, die eine einfache In-Memory-Authentifizierung bietet (gültig für Spring 4):

@Configuration public class InMemoryAuthWebSecurityConfigurer extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("spring") .password("secret") .roles("USER"); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/private/**") .authenticated() .antMatchers("/public/**") .permitAll() .and() .httpBasic(); } } 

Diese Konfiguration definiert die Authentifizierung für alle / private / zugeordnete Methoden und den öffentlichen Zugriff für alle unter / public /.

Wenn wir dieselbe Konfiguration unter Spring Security 5 verwenden, wird der folgende Fehler angezeigt:

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

Der Fehler weist darauf hin, dass das angegebene Kennwort nicht dekodiert werden konnte, da für unsere speicherinterne Authentifizierung kein Kennwortcodierer konfiguriert wurde .

3. Federsicherheit 5

Wir können diesen Fehler beheben, indem wir einen delegierenden PasswordEncoder mit der PasswordEncoderFactories- Klasse definieren.

Wir verwenden diesen Encoder, um unseren Benutzer mit dem AuthenticationManagerBuilder zu konfigurieren :

@Configuration public class InMemoryAuthWebSecurityConfigurer extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); auth.inMemoryAuthentication() .withUser("spring") .password(encoder.encode("secret")) .roles("USER"); } } 

Mit dieser Konfiguration speichern wir jetzt unser In-Memory-Passwort mit BCrypt im folgenden Format:

{bcrypt}$2a$10$MF7hYnWLeLT66gNccBgxaONZHbrSMjlUofkp50sSpBw2PJjUqU.zS 

Obwohl wir unseren eigenen Satz von Kennwortcodierern definieren können, wird empfohlen, die in PasswordEncoderFactories bereitgestellten Standardcodierer beizubehalten .

3.2. NoOpPasswordEncoder

Wenn wir das konfigurierte Passwort aus irgendeinem Grund nicht verschlüsseln möchten, können wir den NoOpPasswordEncoder verwenden .

Dazu stellen wir der Passwortmethode () einfach die Passphrase voran, die wir der Methode password () geben :

@Configuration public class InMemoryNoOpAuthWebSecurityConfigurer extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("spring") .password("{noop}secret") .roles("USER"); } } 

Auf diese Weise verwendet Spring Security den NoOpPasswordEncoder unter der Haube, wenn das vom Benutzer bereitgestellte Kennwort mit dem oben konfigurierten Kennwort verglichen wird.

Beachten Sie jedoch, dass wir diesen Ansatz niemals für die Produktionsanwendung verwenden sollten! Wie in der offiziellen Dokumentation angegeben, ist der NoOpPasswordEncoder veraltet, um anzuzeigen, dass es sich um eine Legacy-Implementierung handelt, und die Verwendung wird als unsicher angesehen .

3.3. Vorhandene Passwörter migrieren

Wir können vorhandene Kennwörter auf die empfohlenen Spring Security 5-Standards aktualisieren, indem wir:

  • Aktualisieren von im Klartext gespeicherten Passwörtern mit ihrem codierten Wert:
String encoded = new BCryptPasswordEncoder().encode(plainTextPassword); 
  • Das Präfixieren von gespeicherten Hash-Passwörtern mit ihrer bekannten Encoder-ID:
{bcrypt}$2a$10$MF7hYnWLeLT66gNccBgxaONZHbrSMjlUofkp50sSpBw2PJjUqU.zS {sha256}97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0 
  • Benutzer werden aufgefordert, ihre Passwörter zu aktualisieren, wenn der Codierungsmechanismus für gespeicherte Passwörter unbekannt ist

4. Fazit

In diesem kurzen Beispiel haben wir eine gültige In-Memory-Authentifizierungskonfiguration für Spring 4 mithilfe des neuen Kennwortspeichermechanismus auf Spring 5 aktualisiert.

Wie immer finden Sie den Quellcode im GitHub-Projekt.