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));