【问题标题】:There is no PasswordEncoder mapped for the id "null" in Spring SecuritySpring Security 中没有为 id "null" 映射 PasswordEncoder
【发布时间】:2020-10-27 09:45:43
【问题描述】:

我正在从 Spring Boot 1.5.12 迁移到 Spring Boot 2.0 以及 Spring Security 5,我正在尝试通过 OAuth 2 进行身份验证。但即使在使用委托 {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;
    }
}

CustomUserDetailsS​​ervice

public interface CustomUserDetailsService extends UserDetailsService {

    UserDetails getByMsisdn(String msisdn);

    void initDummyUsers();
}

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

Spring Boot PasswordEncoder Error

【问题讨论】:

  • 公共接口 CustomUserDetailsS​​ervice 扩展 UserDetailsS​​ervice { UserDetails getByMsisdn(String msisdn);无效的 initDummyUsers(); }
  • 问题已更新

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


【解决方案1】:

The Spring Security documentation is addressing your exact problem.

当存储的密码之一发生以下错误 没有密码存储格式中描述的 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。这 解决它的最简单方法是弄清楚你的密码是怎样的 当前正在存储并明确提供正确的 密码编码器。

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

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

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

或者更好地提供custom defined password encoder delegator

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);

全部取自official spring security docs on password encoding

【讨论】:

    猜你喜欢
    • 2018-09-14
    • 2020-08-11
    • 2020-07-03
    • 2018-10-30
    • 2019-06-02
    • 2018-11-14
    • 2021-06-02
    • 2018-09-11
    相关资源
    最近更新 更多