【发布时间】:2018-09-14 04:48:57
【问题描述】:
我正在从 Spring Boot 1.4.9 迁移到 Spring Boot 2.0 以及 Spring Security 5,我正在尝试通过 OAuth 2 进行身份验证。但是我收到了这个错误:
java.lang.IllegalArgumentException:没有为 id “null”映射 PasswordEncoder
从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:没有为 id “null”映射 PasswordEncoder
为了解决这个问题,我尝试了 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);
}
}
请指导我解决这个问题。我花了几个小时来解决这个问题,但无法解决。
【问题讨论】:
-
我对这个问题的描述性更强。当我从 Spring security 4 切换到 5 时。我遇到了第一个错误,然后我通过更改密码生成器解决了它,它开始给我第二个错误。并且错误消息是不同的。 1)编码密码看起来不像 BCrypt 和 2)java.lang.IllegalArgumentException:没有为 id “null”映射 PasswordEncoder。我目前遇到的第二个问题。
-
我认为问题出在客户端(而不是个人用户帐户)。我个人已经对用户详细信息进行了编码,但没有对客户端进行编码。现在,OAuth2 的用户需要对 client 密码(以及用户密码)进行编码。具体来说,要么在
ClientDetailsServiceConfigurer上设置passwordEncoder,要么在密钥前面加上{noop}。希望这是有道理的,可以帮助别人。 -
运行
mvn clean package为我解决了这个问题。一定是缓存有问题。
标签: java spring spring-boot spring-security spring-security-oauth2