繁体   English   中英

Spring Security 中没有为 id “null”映射 PasswordEncoder

[英]There is no PasswordEncoder mapped for the id “null” in Spring Security

I am migrating from Spring Boot 1.5.12 to Spring Boot 2.0 and also to Spring Security 5 and I am trying to do authenticate via OAuth 2. But I am getting this error even after using delegate {noop}:

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

这是我的代码:

安全配置

public class SecurityConfig extends WebSecurityConfigurerAdapter {

    
    @Autowired
    private CustomUserDetailsService userDetailsService;
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

    public SecurityConfig() {
        super();
        SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
    }

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
            http.cors().and().csrf().disable().exceptionHandling().and().authorizeRequests()
                .antMatchers("/api/v1/**")
                .authenticated().and().httpBasic();
    }

    @Override
    public void configure(final WebSecurity web) throws Exception {
            web.ignoring().antMatchers(
                "/v2/api-docs","/configuration/ui","/swagger-resources", "/configuration/security", "/webjars/**",
                "/swagger-resources/configuration/ui","/swagger-resources/configuration/security",
                "/swagger-ui.html", "/admin11/*", "/*.html", "/*.jsp", "/favicon.ico", "//*.html", "//*.css", "//*.js",
                "/admin11/monitoring","/proxy.jsp");
    }

    @Override
    protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

Oauth2AuthorizationServerConfig

public class Oauth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;

    @Autowired
    private CustomUserDetailsService userDetailsService;
    
    @Autowired
    private JdbcTokenStore jdbcTokenStore;
    
    @Bean
    public TokenStore tokenStore() {
        return jdbcTokenStore;
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        CustomTokenEnhancer converter = new CustomTokenEnhancer();
        converter.setSigningKey("secret_api");
        return converter;
    }

    @Override
    public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
                
        endpoints.tokenStore(tokenStore())
                .accessTokenConverter(accessTokenConverter())
                .authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService)
                .pathMapping("/oauth/token", "/api/v1/oauth/token");
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory().withClient("app").secret("{noop}secret")
                .authorizedGrantTypes("password", "authorization_code").scopes("read", "write")
                .autoApprove(true).accessTokenValiditySeconds(0);
    }

    @Override
    public void configure(final AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
    }
    
    @Bean
    public DefaultTokenServices defaultTokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        return defaultTokenServices;
    }
}

CustomUserDetailsService

public interface CustomUserDetailsService extends UserDetailsService {

    UserDetails getByMsisdn(String msisdn);

    void initDummyUsers();
}

为了解决这个问题,我尝试了 Stackoverflow 的以下问题:

Spring 引导密码编码器错误

Spring 安全文档正在解决您的确切问题。

当存储的密码之一没有密码存储格式中所述的 id 时,会发生以下错误。

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped
for the id "null"
     at org.springframework.security.crypto.password.DelegatingPasswordEncoder$UnmappedIdPasswordEncoder.matches(DelegatingPasswordEncoder.java:233)
     at org.springframework.security.crypto.password.DelegatingPasswordEncoder.matches(DelegatingPasswordEncoder.java:196)

解决该错误的最简单方法是切换为显式提供密码编码所用的 PasswordEncoder。 解决它的最简单方法是弄清楚您的密码当前是如何存储的,并明确提供正确的 PasswordEncoder。

如果您从 Spring Security 4.2.x 迁移,您可以通过公开 NoOpPasswordEncoder bean 恢复到以前的行为。

因此,您应该能够通过显式提供PasswordEncoder来解决此问题

// remember, its bad practice
@Bean
public PasswordEncoder passwordEncoder() {
    return NoOpPasswordEncoder.getInstance();
}

甚至更好地提供自定义的密码编码器委托

String idForEncode = "bcrypt";
Map encoders = new HashMap<>();
encoders.put(idForEncode, new BCryptPasswordEncoder());
encoders.put("noop", NoOpPasswordEncoder.getInstance());
encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
encoders.put("scrypt", new SCryptPasswordEncoder());
encoders.put("sha256", new StandardPasswordEncoder());

PasswordEncoder passwordEncoder =
    new DelegatingPasswordEncoder(idForEncode, encoders);

全部取自官方 spring 密码编码安全文档

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM