Oauth2客户端凭证流+ Spring Boot2抛出对于id“ null”错误,没有映射为>的PasswordEncoder

时间:2019-02-20 08:05:35

标签: java spring spring-boot spring-security spring-security-oauth2

我正在升级现有的客户端凭据Oauth2以使用Spring Boot2。
授权服务器使用具有{em {em1}}的 Base64 编码的基本身份验证 我正在使用 RedisTokenStore 来存储令牌。

我正在为新升级的Oauth2配置所需的配置而苦苦挣扎。我找不到合适的文档将我指向“客户端凭据”流程。
随着Spring 5 Security的更新,密码编码失败,我得到:-

  

java.lang.IllegalArgumentException:没有映射的PasswordEncoder   id为“ null”的错误

以下是我的配置:-

(client:secret)

AuthorizationServer ResourceServer

@Configuration
public class WebConfiguration extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
                http.
                        csrf().disable().
                        authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll();
        }

}

RedisTokenStore

@Configuration
@EnableAuthorizationServer
public class Oauth2Configuration extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private ClientDetailsService clientDetailsService;

    @Autowired
    private JedisConnectionFactory jedisConnFactory;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(clientDetailsService);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore());
        super.configure(endpoints);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        String idForEncode = "bcrypt";
        Map<String, PasswordEncoder> encoderMap = new HashMap<>();
        encoderMap.put(idForEncode, new BCryptPasswordEncoder());
        return new DelegatingPasswordEncoder(idForEncode, encoderMap);
    }

    @Bean
    public TokenStore tokenStore() {
        return new Oauth2TokenStore(jedisConnFactory);
    }

    @Configuration
    @EnableResourceServer
    protected static class ResourceServer extends ResourceServerConfigurerAdapter {

        @Override
        public void configure(HttpSecurity http) throws Exception {
            http
                    .authorizeRequests()
                    .antMatchers("/verify_token").authenticated()
                    .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                    .antMatchers(HttpMethod.GET, "/info").permitAll()
                    .antMatchers(HttpMethod.GET, "/health").permitAll();
        }
    }
}

在更新Spring安全密码编码后,当我存储在Redis存储中时,我还需要对令牌进行编码吗?

1 个答案:

答案 0 :(得分:2)

此错误意味着所存储的密码没有以密码类型作为前缀。

例如,您的哈希密码可能类似于:

$2a$10$betZ1XaM8rTUQHwWS.cyIeTKJySBfZsmC3AYxYjwa4fHtr6i/.9oG

但是,Spring Security现在期望:

{bcrypt}$2a$10$betZ1XaM8rTUQHwWS.cyIeTKJySBfZsmC3AYxYjwa4fHtr6i/.9oG

您基本上有two options。首先是将DelegatingPasswordEncoder配置为默认值:

@Bean
public PasswordEncoder passwordEncoder() {
    String idForEncode = "bcrypt";
    BCryptPasswordEncoder bcrypt = new BCryptPasswordEncoder();
    Map<String, PasswordEncoder> encoderMap = 
        Collections.singletonMap(idForEncode, bcrypt);
    DelegatingPasswordEncoder delegating =
        new DelegatingPasswordEncoder(idForEncode, encoderMap);
    delegating.setDefaultPasswordEncoderForMatches(bcrypt);
    return delegating;
}

或者第二种方法是对密码存储进行批量升级(使用{bcrypt}前缀)。

我不确定您的ClientDetailsService是从哪里来的,但我会开始在那寻找。

更新:但是,这假定您现有的密码已被加密。如果不是,那么您将提供合适的编码器:

@Bean
public PasswordEncoder passwordEncoder() {
    String idForEncode = "bcrypt";
    PasswordEncoder existing = new MyPasswordEncoder();
    PasswordEncoder updated = new BCryptPasswordEncoder();
    Map<String, PasswordEncoder> encoderMap = 
        Collections.singletonMap(idForEncode, updated);
    DelegatingPasswordEncoder delegating =
        new DelegatingPasswordEncoder(idForEncode, encoderMap);
    delegating.setDefaultPasswordEncoderForMatches(existing);
    return delegating;
}