Spring Security 5の新しいパスワードストレージ

1前書き

  • 最新のSpring Securityリリースで、多くのことが変わりました。そのうちの1つが、アプリケーションでパスワードのエンコードを処理する方法です。

このチュートリアルでは、これらの変更点のいくつかについて説明します。

後で、新しい委任メカニズムの設定方法と既存のパスワードエンコードの更新方法について説明します。ユーザーの認識はありません。

** 2 Spring Security 5.xでの関連する変更

Spring Securityチームは、 org.springframework.security.authentication.encoding PasswordEncoder を非推奨として宣言しました。古いインターフェースはランダムに生成されたsalt用に設計されていなかったので、それは論理的な動きでした。その結果、バージョン5ではこのインタフェースが削除されました。

さらに、Spring Securityはエンコードされたパスワードを処理する方法を変更します。以前のバージョンでは、各アプリケーションは1つのパスワードエンコードアルゴリズムのみを採用していました。

デフォルトでは、 StandardPasswordEncoder がそれを処理しました。エンコードにはSHA-256を使用しました。パスワードエンコーダを変更することで、他のアルゴリズムに切り替えることができます。しかし、私たちのアプリケーションは厳密に1つのアルゴリズムに固執する必要がありました。

  • バージョン5.0では、パスワードエンコードの委任の概念が導入されました** これで、パスワードごとに異なるエンコードを使用できるようになりました。 Springは、エンコードされたパスワードの前に付けられた識別子によってアルゴリズムを認識します。

これがbcryptでエンコードされたパスワードの例です。

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

最初の段階で、中かっこでbcryptが指定されていることに注意してください。

3委任構成

  • パスワードハッシュが接頭辞を持たない場合、委任プロセスはデフォルトのエンコーダを使用します。

そのため、以前のSpring Securityバージョンのデフォルト設定と互換性があります。

バージョン5では、Spring Securityは__PasswordEncoderFactories.createDelegatingPasswordEncoder()を導入します。

接頭辞のないパスワードの場合、そのインスタンスによって、前述のデフォルトの動作が保証されます。また、プレフィックスを含むパスワードハッシュの場合、委任はそれに応じて行われます。

Spring Securityチームはサポートされているアルゴリズムをhttps://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/crypto/factory/PasswordEncoderFactories.html#の最新バージョンにリストしている。 createDelegatingPasswordEncoder - [対応するJavaDoc]

もちろん、Springではこの動作を設定できます。

サポートしたいとしましょう。

私たちの新しいデフォルトとして** bcrypt

代替として** scrypt

現在使用されているアルゴリズムとして** SHA-256。

このセットアップの設定は次のようになります。

@Bean
public PasswordEncoder delegatingPasswordEncoder() {
    PasswordEncoder defaultEncoder = new StandardPasswordEncoder();
    Map<String, PasswordEncoder> 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パスワードエンコードアルゴリズムの移行

前のセクションでは、必要に応じてパスワードエンコーディングを設定する方法について説明しました。そのため、ここでは既にエンコードされたパスワードを新しいアルゴリズムに切り替える方法について説明します。

エンコーディングを SHA-256 から bcrypt に変更したいとします。ただし、ユーザーにパスワードを変更させたくはありません。

考えられる解決策の1つは、ログイン要求を使用することです。この時点で、認証情報にプレーンテキストでアクセスできます。それが現在のパスワードを取得してそれを再エンコードすることができる瞬間です。

その結果、Springの AuthenticationSuccessEvent を使用できます。このイベントは、ユーザーがアプリケーションに正常にログインした後に発生します。**

これがサンプルコードです:

@Bean
public ApplicationListener<AuthenticationSuccessEvent>
  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();
        }
    };
}

前のスニペットでは:

  • 提供されているものからユーザーパスワードをクリアテキストで取得しました

認証詳細 ** 新しいアルゴリズムで新しいパスワードハッシュを作成しました

  • 認証トークンからクリアテキストのパスワードを削除しました

  • デフォルトでは、Spring Securityがパスワードをできるだけ早く削除するため、クリアテキストでパスワードを抽出することは不可能です。

したがって、クリアテキストバージョンのパスワードを保持するようにSpringを設定する必要があります。

さらに、エンコーディング委任を登録する必要があります。

@Configuration
public class PasswordStorageWebSecurityConfigurer
  extends WebSecurityConfigurerAdapter {

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

   //...
}

5結論

このクイック記事では、5.xで利用可能な新しいパスワードエンコード機能について説明しました。

パスワードをエンコードするために複数のパスワードエンコードアルゴリズムを設定する方法も見ました。さらに、既存のものを壊すことなく、パスワードのエンコーディングを変更する方法を検討しました。

最後に、Springイベントを使用して暗号化されたユーザーパスワードを透過的に更新する方法について説明しました。これにより、ユーザーに公開することなくエンコード戦略をシームレスに変更できます。

最後にそしていつものように、すべてのコード例は私たちのhttps://github.com/eugenp/tutorials/tree/master/spring-5-security[GitHub repository]で利用可能です。