Spring Security 5:没有为id“null”映射PasswordEncoder
我正在从Spring Boot 1.4.9迁移到Spring Boot 2.0以及Spring Security 5,我正在尝试通过OAuth 2进行身份validation。但是我收到此错误:
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
随着第一个错误消失,现在当我尝试进行身份validation时,我得到以下错误:
java.lang.IllegalArgumentException:没有为id“null”映射PasswordEncoder
为了解决这个问题,我尝试了Stackoverflow的以下所有问题:
-
Spring Boot PasswordEncoder错误
-
Spring Oauth2。 密码编码器未在DaoAuthenticationProvider中设置
这是一个类似于我的问题,但没有回答:
- Spring Security 5 – 密码迁移
注意:我已将加密密码存储在数据库中,因此无需再在UserDetailsService
进行编码。
在Spring security 5文档中,他们建议您可以使用以下方法处理此exception:
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
,还必须将新密码存储格式应用于客户机密钥。
.secret("{noop}secret")
对于任何面临同样问题并且不需要安全解决方案的人 – 主要用于测试和调试 – 在内存中仍然可以配置用户。
这只是为了玩游戏 – 没有现实世界的场景。
以下使用的方法已弃用。
这是我得到它的地方:
- 资源
- 参考,也在上面的来源中提到
在您的WebSecurityConfigurerAdapter
添加以下内容:
@SuppressWarnings("deprecation") @Bean public static NoOpPasswordEncoder passwordEncoder() { return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance(); }
显然,密码是经过哈希处理的,但仍可在内存中使用。
当然,您也可以使用像BCryptPasswordEncoder
这样的真实PasswordEncoder
并在密码前加上正确的id:
// Create an encoder with strength 16 BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16); String result = encoder.encode("myPassword"); assertTrue(encoder.matches("myPassword", result));