微服务简单案例可以参照使用Spring Cloud Security OAuth2搭建授权服务。
spring-cloud--security /oauth/token 报错401。
错误信息如下:
java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
在网上看了好多,都说是由于现在的spring security密码格式变化。
{id}encodedPassword
但是我使用了还是有问题。最后在Spring Security 5.0的DelegatingPasswordEncoder详解找到了始末,也自己跟踪了代码发现确实如此。
public class DelegatingPasswordEncoder implements PasswordEncoder {
private PasswordEncoder defaultPasswordEncoderForMatches = new DelegatingPasswordEncoder.UnmappedIdPasswordEncoder();
public boolean matches(CharSequence rawPassword, String prefixEncodedPassword) {
if (rawPassword == null && prefixEncodedPassword == null) {
return true;
} else {
String id = this.extractId(prefixEncodedPassword); //1.这里我们没有指定PasswordEncoder 是null
PasswordEncoder delegate = (PasswordEncoder)this.idToPasswordEncoder.get(id);
if (delegate == null) {
return this.defaultPasswordEncoderForMatches.matches(rawPassword, prefixEncodedPassword); //2.进入这里
} else {
String encodedPassword = this.extractEncodedPassword(prefixEncodedPassword);
return delegate.matches(rawPassword, encodedPassword);
}
}
}
//内部类
private class UnmappedIdPasswordEncoder implements PasswordEncoder {
private UnmappedIdPasswordEncoder() {
}
public String encode(CharSequence rawPassword) {
throw new UnsupportedOperationException("encode is not supported");
}
//3.最终调用,也就是我们看到的异常信息
public boolean matches(CharSequence rawPassword, String prefixEncodedPassword) {
String id = DelegatingPasswordEncoder.this.extractId(prefixEncodedPassword);
throw new IllegalArgumentException("There is no PasswordEncoder mapped for the id \"" + id + "\"");
}
}
}
升级之后`DelegatingPasswordEncoder`中要求提供自定义的PasswordEncoder。对于使用spring security的人肯定是够了。如下:
public class MyWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()) //1.第一处
.withUser("user1").
password(new BCryptPasswordEncoder().encode("123456")) //2.第二处
.roles("USER");
}
}
但是如果你使用的spring-cloud-starter-oauth2,那还需要进行其他的配置。
@Configuration
public class MyAuthorizationServerConfigurerAdapter extends AuthorizationServerConfigurerAdapter {
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
clients.inMemory()
.withClient("client")
.secret(new BCryptPasswordEncoder().encode("secret")) //1.第一处
.authorizedGrantTypes("authorization_code")
.scopes("app")
.redirectUris("http://www.baidu.com");
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.allowFormAuthenticationForClients()
.passwordEncoder(new BCryptPasswordEncoder()); //2.第二处
}
}