我正在从Spring Boot 1.4.9迁移到Spring Boot 2.0,并升级到Spring Security 5,尝试通过OAuth 2进行身份验证。但是遇到以下错误:
java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
根据Spring Security 5的文档,密码存储格式已更改。
在我的当前代码中,我已创建了密码编码器bean:
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
然而我遇到了以下错误:
加密后的密码看起来不像是BCrypt格式
因此,我按照Spring Security 5文档更新了编码器:
@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
现在,如果我可以在数据库中看到密码,它会被存储为:
{bcrypt}$2a$10$LoV/3z36G86x6Gn101aekuz3q9d7yfBp3jFn7dzNN/AL5630FyUQ
解决了第一个错误之后,现在我尝试进行身份验证时,遇到以下错误:
java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null
为了解决这个问题,我尝试了Stackoverflow上所有以下问题的解答:
以下是类似于我的问题,但没有答案的问题:
注意:我已经将加密密码存储在数据库中,因此不需要在UserDetailsService
中再次编码。
在Spring security 5文档中,他们建议使用以下方式处理此异常:
DelegatingPasswordEncoder.setDefaultPasswordEncoderForMatches(PasswordEncoder)
如果这是解决方案,那么我应该把它放在哪里?我已经尝试将其放置在PasswordEncoder
bean中,但它没有起作用:
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
上设置passwordEncoder
或在密码前加上{noop}前缀。希望这有助于解决问题。 - KellyMmvn clean package
命令已经被解决了。可能是缓存的问题。 - Janac Meena