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]で利用可能です。