본문 바로가기

Spring 정리ver2/Security

[baeldung] Default Password Encoder in Spring Security 5

728x90

 

Spring Security 4에서는 메모리 내 인증을 사용하여 일반 텍스트로 비밀번호를 저장할 수 있었다.

그러나 Spring Security 5는 암호 관리 프로세스에 대한 대대적인 점검으로 암호 인코딩 및 디코딩을 위한 보다 안전한 기본 메커니즘이 도입되었다

 

 

Spring Security 4

We'll start by showing a standard security configuration that provides simple in-memory authentication 

Spring 4 의 예시

@Configuration
public class InMemoryAuthWebSecurityConfigurer 
  extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) 
      throws Exception {
        auth.inMemoryAuthentication()
          .withUser("spring")
          .password("secret")
          .roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
          .antMatchers("/private/**")
          .authenticated()
          .antMatchers("/public/**")
          .permitAll()
          .and()
          .httpBasic();
    }
}

이 구성은 모든 /private/ 매핑된 메서드에 대한 인증과 /public/ 아래의 모든 항목에 대한 공용 액세스를 정의한다

 

 

Spring Security 5에서 동일한 구성을 사용하면 다음 오류가 발생한다.

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

 

 

이 오류는 메모리 내 인증을 위해 구성된 비밀번호 인코더가 없기 때문에 지정된 비밀번호를 디코딩할 수 없다는 뜻이다

 

 

 

 

 

 

 

Spring Security 5

PasswordEncoderFactories 클래스 로 Delegating PasswordEncoder를 정의하여 위의 오류를 수정한다

해당 인코더를 사용하여 사용자를 구성한다 ( BCrypt를 사용하여 메모리 내 암호를 다음 형식으로 저장 )

@Configuration
public class InMemoryAuthWebSecurityConfigurer {

    @Bean
    public InMemoryUserDetailsManager userDetailsService() {
        PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        UserDetails user = User.withUsername("spring")
            .password(encoder.encode("secret"))
            .roles("USER")
            .build();
        return new InMemoryUserDetailsManager(user);
    }
}
{bcrypt}$2a$10$MF7hYnWLeLT66gNccBgxaONZHbrSMjlUofkp50sSpBw2PJjUqU.zS

자체 비밀번호 인코더 세트를 정의할 수 있지만 PasswordEncoderFactories 에서 제공되는 기본 인코더를 사용하는 것이 좋다

Spring Security 버전 5.7.0-M2부터 Spring은   WebSecurityConfigureAdapter의 사용을 더 이상 사용하지 않으며 WebSecurityConfigureAdapter 없이 구성을 생성할 것을 제안하고 있다

 

 

 

 

NoOpPasswordEncoder

만약 인코딩을 원하지 않으면 이를 사용하면 된다

If, for any reason, we don't want to encode the configured password, we can make use of the NoOpPasswordEncoder.

To do so, we simply prefix the passphrase we provide to the password() method with the {noop} identifier:

@Configuration
public class InMemoryNoOpAuthWebSecurityConfigurer {

    @Bean
    public InMemoryUserDetailsManager userDetailsService() {
        UserDetails user = User.withUsername("spring")
            .password("{noop}secret")
            .roles("USER")
            .build();
        return new InMemoryUserDetailsManager(user);
    }
}

 Spring Security는 사용자가 제공한 비밀번호와 위에서 구성한 비밀번호를 비교할 때 후드 아래에서 NoOpPasswordEncoder를 사용한다

 프로덕션 애플리케이션에서는 이 접근 방식을 사용해서는 안된다. 공식 문서에서 알 수 있듯이 NoOpPasswordEncoder는 레거시 구현임을 나타내기 위해 더 이상 사용되지 않으며 이를 사용하는 것은 안전하지 않은 것으로 간주하고 있다

 

 

 

Migrating Existing Passwords

We can update existing passwords to the recommended Spring Security 5 standards by:

  • Updating plain text stored passwords with their value encoded: 암호화된 값으로 저장된 일반 텍스트 암호 업데이트
String encoded = new BCryptPasswordEncoder().encode(plainTextPassword);
  • Prefixing hashed stored passwords with their known encoder identifier 알려진 인코더 식별자로 해시된 저장된 비밀번호 접두사 추가
{bcrypt}$2a$10$MF7hYnWLeLT66gNccBgxaONZHbrSMjlUofkp50sSpBw2PJjUqU.zS
{sha256}97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0
  • Requesting users to update their passwords when the encoding-mechanism for stored passwords is unknown

 

728x90