【Spring Boot】Spring Boot 2.x + Spring Security OAuth2 2.3.3 出现 bad client credentials 错误的踩坑记录
【Spring Boot】Spring Boot 2.x + Spring Security OAuth2 2.3.3 出现 bad client credentials 错误的踩坑记录
环境:
spring boot 2.0.4.RELEASE
spring security oauth 2.3.3.RELEASE
OAuth2的配置
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userService;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.allowFormAuthenticationForClients();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client_1")
.secret("123456")
.authorizedGrantTypes("password", "refresh_token")
.scopes("read", "write")
.accessTokenValiditySeconds(10000)
.refreshTokenValiditySeconds(10000);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints){
endpoints.authenticationManager(authenticationManager)
.userDetailsService(userService);
}
}
Spring Security配置
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
}
}
使用postman进行请求时,会提示bad client credentials
{
"error": "invalid_client",
"error_description": "Bad client credentials"
}
该请求甚至没有走到 UserDetailService 就已经被返回,很是诡异。
在网上搜索,查找相关技术博客,都无果。
其实问题出在 PasswordEncoder 身上,网上很多说明都没有写这个Bean的配置,如果不配置这个Bean的话AuthenticationManager 是直接初始化失败的,而Spring Security自带的这个Encoder,是对密码进行了一层加密,如果我们传铭文进去是会被直接报warn的log并且返回。
正确的使用姿势是:
@Bean
public PasswordEncoder passwordEncoder() {
return new PasswordEncoder() {
@Override
public String encode(CharSequence charSequence) {
return charSequence.toString();
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return Objects.equals(charSequence.toString(),s);
}
};
}
这样请求就一切正常了,当然,实际应用中是不推荐这样的,因为数据库中存储的密码应当是加密过后的,明文密码后患无穷。