1. ホーム
  2. java

[解決済み] Spring Security 5 : id "null "に対応するPasswordEncoderが存在しない。

2022-02-27 15:55:34

質問

Spring Boot 1.4.9からSpring Boot 2.0、Spring Security 5に移行し、OAuth 2で認証しようとしているのですが、このエラーが発生します。

java.lang.IllegalArgumentException: id "nullに対応するPasswordEncoderがありません。

のドキュメントより Spring Security 5 ということを知りました。 パスワードの保存形式が変更されました。

現在のコードでは、パスワード・エンコーダ・ビーンを次のように作成しています。

@Bean
public BCryptPasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

しかし、以下のようなエラーが発生しました。

暗号化されたパスワードはBCryptのように見えません

ということで、エンコーダを更新してみると 春のセキュリティー5 という文書に変更しました。

@Bean
public PasswordEncoder passwordEncoder() {
    return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}

データベースでパスワードを確認すると、次のように保存されています。

{bcrypt}$2a$10$LoV/3z36G86x6Gn101aekuz3q9d7yfBp3jFn7dzNN/AL5630FyUQ

1つ目のエラーはなくなり、現在、認証を行おうとすると、以下のエラーが表示されます。

java.lang.IllegalArgumentException: ID "nullに対応するPasswordEncoderがありません。

この問題を解決するために、私はStackoverflowから以下の質問をすべて試してみました。

同じような質問で、回答がないものを紹介します。

注:すでに暗号化されたパスワードをデータベースに保存しているので、再度 UserDetailsService .

での 春のセキュリティ5 を使用してこの例外を処理できることを示唆しています。

<ブロッククオート

DelegatingPasswordEncoder.setDefaultPasswordEncoderForMatches(PasswordEncoder)

もしこれが修正であるなら、どこにそれを置くべきでしょうか?私は、これを PasswordEncoder のようなビーンがありますが、うまくいきませんでした。

DelegatingPasswordEncoder def = new DelegatingPasswordEncoder(idForEncode, encoders);
def.setDefaultPasswordEncoderForMatches(passwordEncoder);

MyWebSecurity クラス

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Override
    public void configure(WebSecurity web) throws Exception {

        web
                .ignoring()
                .antMatchers(HttpMethod.OPTIONS)
                .antMatchers("/api/user/add");
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

MyOauth2 の設定

@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

    @Bean
    public TokenStore tokenStore() {
        return new InMemoryTokenStore();
    }

    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;


    @Bean
    public TokenEnhancer tokenEnhancer() {
        return new CustomTokenEnhancer();
    }

    @Bean
    public DefaultAccessTokenConverter accessTokenConverter() {
        return new DefaultAccessTokenConverter();
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints)
            throws Exception {
        endpoints
                .tokenStore(tokenStore())
                .tokenEnhancer(tokenEnhancer())
                .accessTokenConverter(accessTokenConverter())
                .authenticationManager(authenticationManager);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients
                .inMemory()
                .withClient("test")
                .scopes("read", "write")
                .authorities(Roles.ADMIN.name(), Roles.USER.name())
                .authorizedGrantTypes("password", "refresh_token")
                .secret("secret")
                .accessTokenValiditySeconds(1800);
    }
}

この問題についてご指導ください。この問題を解決するために何時間も費やしましたが、解決することができませんでした。

どうすればいいですか?

を設定する際に ClientDetailsServiceConfigurer を適用する必要があります。 パスワード保存形式 をクライアントシークレットに追加します。

.secret("{noop}secret")