복붙노트

[SPRING] Spring Security 5 : "null"id에 매핑 된 PasswordEncoder가 없다.

SPRING

Spring Security 5 : "null"id에 매핑 된 PasswordEncoder가 없다.

스프링 부트 1.4.9에서 스프링 부트 2.0으로 마이그레이션 중이며 스프링 시큐리티 5로 마이그레이션 중이며 OAuth 2를 통해 인증을 시도하고 있습니다. 그러나이 오류가 발생합니다.

스프링 시큐리티 5의 문서에서 나는 암호의 저장 형식이 변경됩니다.

현재 코드에서 암호 인코더 빈을 다음과 같이 작성했습니다.

@Bean
public BCryptPasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

그러나 그것은 나를 아래 오류주고있다 :

따라서 Spring Security 5 문서에 따라 인코더를 다음과 같이 업데이트합니다.

@Bean
public PasswordEncoder passwordEncoder() {
    return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}

이제 데이터베이스에서 암호를 볼 수 있다면

{bcrypt}$2a$10$LoV/3z36G86x6Gn101aekuz3q9d7yfBp3jFn7dzNN/AL5630FyUQ

첫 번째 오류가 사라지고 이제 인증을 시도 할 때 오류가 발생합니다.

이 문제를 해결하기 위해 나는 아래의 모든 질문을 Stackoverflow에서 시도했다 :

내 질문과 비슷하지만 답이 없다.

참고 : 이미 데이터베이스에 암호화 된 암호를 저장하고 있으므로 UserDetailsService에서 다시 인코딩 할 필요가 없습니다.

Spring 보안 문서에서 그들은 다음을 사용하여이 예외를 처리 할 수 ​​있다고 제안했다.

이것이 수정이라면 어디에 넣어야합니까? 아래처럼 PasswordEncoder 빈에 넣으려고했지만 작동하지 않았습니다.

DelegatingPasswordEncoder def = new DelegatingPasswordEncoder(idForEncode, encoders);
def.setDefaultPasswordEncoderForMatches(passwordEncoder);

MyWebSecurity 클래스

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Override
    public void configure(WebSecurity web) throws Exception {

        web
                .ignoring()
                .antMatchers(HttpMethod.OPTIONS)
                .antMatchers("/api/user/add");
    }

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

MyOauth2 구성

@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

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

    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;


    @Bean
    public TokenEnhancer tokenEnhancer() {
        return new CustomTokenEnhancer();
    }

    @Bean
    public DefaultAccessTokenConverter accessTokenConverter() {
        return new DefaultAccessTokenConverter();
    }

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

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients
                .inMemory()
                .withClient("test")
                .scopes("read", "write")
                .authorities(Roles.ADMIN.name(), Roles.USER.name())
                .authorizedGrantTypes("password", "refresh_token")
                .secret("secret")
                .accessTokenValiditySeconds(1800);
    }
}

이 문제로 저를 안내해주십시오. 이 문제를 해결하는 데 몇 시간을 허비했지만 해결할 수는 없습니다.

해결법

  1. ==============================

    1.ClientDetailsServiceConfigurer를 구성 할 때 클라이언트 비밀 번호에 새 암호 저장 형식을 적용해야합니다.

    ClientDetailsServiceConfigurer를 구성 할 때 클라이언트 비밀 번호에 새 암호 저장 형식을 적용해야합니다.

    .secret("{noop}secret")
    
  2. ==============================

    2.똑같은 문제에 직면 해 있고 보안 솔루션이 필요하지 않은 사람이라면 (주로 테스트 및 디버깅을 위해) 메모리 사용자는 여전히 구성 할 수 있습니다.

    똑같은 문제에 직면 해 있고 보안 솔루션이 필요하지 않은 사람이라면 (주로 테스트 및 디버깅을 위해) 메모리 사용자는 여전히 구성 할 수 있습니다.

    이것은 놀기위한 것입니다. 실제 시나리오는 없습니다.

    아래에 사용 된 접근법은 더 이상 사용되지 않습니다.

    이것은 내가 어디에서 왔는지입니다.

    WebSecurityConfigurerAdapter에서 다음을 추가하십시오.

    @SuppressWarnings("deprecation")
    @Bean
    public static NoOpPasswordEncoder passwordEncoder() {
    return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
    }
    

    분명히 암호는 해시되었지만 여전히 메모리에서 사용할 수 있습니다.

    물론 BCryptPasswordEncoder와 같은 실제 PasswordEncoder를 사용하고 암호 앞에 올바른 ID를 추가 할 수도 있습니다.

    // Create an encoder with strength 16
    BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16);
    String result = encoder.encode("myPassword");
    assertTrue(encoder.matches("myPassword", result));
    
  3. from https://stackoverflow.com/questions/49654143/spring-security-5-there-is-no-passwordencoder-mapped-for-the-id-null by cc-by-sa and MIT license