Spring Security 5: Нет PasswordEncoder, сопоставленного для идентификатора " null"

Я мигрирую с Spring Boot 1.4.9 на Spring Boot 2.0, а также на Spring Security 5, и я пытаюсь выполнить аутентификацию через OAuth 2. Но я получаю эту ошибку:

java.ленг.IllegalArgumentException: для идентификатора " null

из документации Весенняя Безопасность 5, я узнаю, что изменен формат хранения пароля.

в моем текущем коде я создал свой кодировщик паролей bean as:

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

однако это давало мне ниже ошибку:

закодированный пароль не похож на BCrypt

поэтому я обновляю кодировщик согласно Весенняя Безопасность 5 документ:

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

теперь, если я вижу пароль в базе данных, он хранится как

{bcrypt}a$LoV/3z36G86x6Gn101aekuz3q9d7yfBp3jFn7dzNN/AL5630FyUQ

С этой ошибкой 1st ушел, и теперь, когда я пытаюсь сделать аутентификацию, я получаю ниже ошибка:

java.ленг.IllegalArgumentException: для идентификатора " null

чтобы решить эту проблему, я попробовал все приведенные ниже вопросы из 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);
    }
}

пожалуйста, направьте меня с этой проблемой. Я потратил часы, чтобы исправить это, но не в состоянии исправить.

2 ответов


при настройке ClientDetailsServiceConfigurer, вы также должны применить новый формат хранения паролей к секрету клиента.

.secret("{noop}secret")

для тех, кто сталкивается с той же проблемой и не нуждается в безопасные решения для тестирования и отладки, в основном - в пользователей памяти можно настроить.

это просто для игры - не реальный сценарий.

подход, используемый ниже, является устаревшим.

вот откуда я его взял:


в своем WebSecurityConfigurerAdapter добавить следующее:

@SuppressWarnings("deprecation")
@Bean
public static NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}

здесь, очевидно, пароли хэшируются, но все еще доступны в памяти.


конечно, вы также можете использовать реальные PasswordEncoder как BCryptPasswordEncoder и префикс пароля с правильным идентификатором:

// Create an encoder with strength 16
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16);
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));