Neue Passwortspeicherung in Spring Security 5

Neue Passwortspeicherung im Frühjahr Sicherheit 5

1. Einführung

Mit der neuesten Version von Spring Security hat sich viel geändert. Eine dieser Änderungen ist, wie wir mit der Kennwortkodierung in unseren Anwendungen umgehen können.

In diesem Tutorial werden wir einige dieser Änderungen untersuchen.

Später erfahren Sie, wie Sie den neuen Delegierungsmechanismus konfigurieren und unsere vorhandene Kennwortkodierung aktualisieren, ohne dass unsere Benutzer dies erkennen.

2. Relevante Änderungen in der Frühlingssicherheit 5.x.

Das Spring Security-Team hat diePasswordEncoder inorg.springframework.security.authentication.encoding als veraltet deklariert. Dies war ein logischer Schritt, da die alte Benutzeroberfläche nicht für ein zufällig generiertes Salz ausgelegt war. Folglich hat Version 5 diese Schnittstelle entfernt.

Darüber hinaus ändert Spring Security den Umgang mit verschlüsselten Passwörtern. In früheren Versionen verwendete jede Anwendung nur einen Kennwortkodierungsalgorithmus.

Standardmäßig hat sichStandardPasswordEncoderdamit befasst. Es wurde SHA-256 für die Codierung verwendet. Durch Ändern des Passwortcodierers könnten wir zu einem anderen Algorithmus wechseln. Unsere Anwendung musste sich jedoch an genau einen Algorithmus halten.

Version 5.0 introduces the concept of password encoding delegation. Jetzt können wir verschiedene Codierungen für verschiedene Passwörter verwenden. Spring erkennt den Algorithmus an einem Bezeichner, der dem verschlüsselten Passwort vorangestellt ist.

Hier ist ein Beispiel für ein bcrypt-codiertes Passwort:

{bcrypt}$2b$12$FaLabMRystU4MLAasNOKb.HUElBAabuQdX59RWHq5X.9Ghm692NEi

Beachten Sie, wie bcrypt am Anfang in geschweiften Klammern angegeben wird.

3. Delegierungskonfiguration

If the password hash has no prefix, the delegation process uses a default encoder. Daher erhalten wir standardmäßig dieStandardPasswordEncoder.

Dadurch ist es mit der Standardkonfiguration früherer Spring Security-Versionen kompatibel.

In Version 5 führt Spring SecurityPasswordEncoderFactories.createDelegatingPasswordEncoder(). ein. Diese Factory-Methode gibt eine konfigurierte Instanz vonDelegationPasswordEncoder zurück.

Bei Kennwörtern ohne Präfix stellt diese Instanz das gerade erwähnte Standardverhalten sicher. Und für Passwort-Hashes, die ein Präfix enthalten, erfolgt die Delegierung entsprechend.

Das Spring Security-Team listet die unterstützten Algorithmen in der neuesten Version voncorresponding JavaDoc auf.

Natürlich können wir dieses Verhalten in Spring konfigurieren.

Nehmen wir an, wir möchten Folgendes unterstützen:

  • bcrypt als unser neuer Standard

  • scrypt als Alternative

  • SHA-256 als aktuell verwendeter Algorithmus.

Die Konfiguration für dieses Setup sieht folgendermaßen aus:

@Bean
public PasswordEncoder delegatingPasswordEncoder() {
    PasswordEncoder defaultEncoder = new StandardPasswordEncoder();
    Map encoders = new HashMap<>();
    encoders.put("bcrypt", new BCryptPasswordEncoder());
    encoders.put("scrypt", new SCryptPasswordEncoder());

    DelegatingPasswordEncoder passworEncoder = new DelegatingPasswordEncoder(
      "bcrypt", encoders);
    passworEncoder.setDefaultPasswordEncoderForMatches(defaultEncoder);

    return passworEncoder;
}

4. Migrieren des Passwortcodierungsalgorithmus

Im vorherigen Abschnitt haben wir untersucht, wie Sie die Kennwortverschlüsselung gemäß Ihren Anforderungen konfigurieren können. Therefore, now we’ll work on how to switch an already encoded password to a new algorithm.

Stellen wir uns vor, wir möchten die Codierung vonSHA-256 inbcrypt ändern. Wir möchten jedoch nicht, dass unser Benutzer seine Passwörter ändert.

Eine mögliche Lösung besteht darin, die Anmeldeanforderung zu verwenden. Zu diesem Zeitpunkt können wir im Klartext auf die Anmeldeinformationen zugreifen. In diesem Moment können wir das aktuelle Passwort übernehmen und neu verschlüsseln.

Folglich können wir dafür dieAuthenticationSuccessEventvon Spring verwenden. Dieses Ereignis wird ausgelöst, nachdem sich ein Benutzer erfolgreich bei unserer Anwendung angemeldet hat.

Hier ist der Beispielcode:

@Bean
public ApplicationListener
  authenticationSuccessListener( PasswordEncoder encoder) {
    return (AuthenticationSuccessEvent event) -> {
        Authentication auth = event.getAuthentication();

        if (auth instanceof UsernamePasswordAuthenticationToken
          && auth.getCredentials() != null) {

            CharSequence clearTextPass = (CharSequence) auth.getCredentials();
            String newPasswordHash = encoder.encode(clearTextPass);

            // [...] Update user's password

            ((UsernamePasswordAuthenticationToken) auth).eraseCredentials();
        }
    };
}

Im vorherigen Snippet:

  • Wir haben das Benutzerpasswort im Klartext aus den angegebenen Authentifizierungsdetails abgerufen

  • Erstellt einen neuen Passwort-Hash mit dem neuen Algorithmus

  • Das Klartextkennwort wurde aus dem Authentifizierungstoken entfernt

Standardmäßig ist das Extrahieren des Kennworts im Klartext nicht möglich, da Spring Security es so schnell wie möglich löscht.

Daher müssen wir Spring so konfigurieren, dass die Klartextversion des Kennworts erhalten bleibt.

Zusätzlich müssen wir unsere Kodierungsdelegation registrieren:

@Configuration
public class PasswordStorageWebSecurityConfigurer
  extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth)
      throws Exception {
        auth.eraseCredentials(false)
          .passwordEncoder(delegatingPasswordEncoder());
    }

    // ...
}

5. Fazit

In diesem kurzen Artikel haben wir uns mit einigen neuen Funktionen zur Kennwortverschlüsselung befasst, die in 5.x verfügbar sind.

Wir haben auch gesehen, wie mehrere Passwort-Verschlüsselungsalgorithmen konfiguriert werden, um unsere Passwörter zu verschlüsseln. Darüber hinaus haben wir eine Möglichkeit untersucht, die Kennwortkodierung zu ändern, ohne die vorhandene zu beschädigen.

Zuletzt haben wir beschrieben, wie Sie mithilfe von Spring-Ereignissen das verschlüsselte Benutzerkennwort transparent aktualisieren und so unsere Kodierungsstrategie nahtlos ändern können, ohne dies unseren Benutzern mitzuteilen.

Schließlich und wie immer sind alle Codebeispiele in unserenGitHub repository verfügbar.