1. 소개

최신 Spring Security 릴리스로 많은 것이 변경되었습니다. 이러한 변경 사항 중 하나는 애플리케이션에서 암호 인코딩을 처리하는 방법입니다.

이 예제에서는 이러한 변경 사항 중 일부를 살펴 보겠습니다.

나중에 새로운 위임 메커니즘을 구성하는 방법과 사용자가 인식하지 못하는 기존 암호 인코딩을 업데이트하는 방법을 살펴 보겠습니다.

2. Spring Security 5.x의 관련 변경 사항

Spring Security 팀은 선언 되는 PasswordEncoder 에서 org.springframework.security.authentication.encoding을 되지 않는 것으로. 이전 인터페이스는 무작위로 생성 된 솔트 용으로 설계되지 않았기 때문에 논리적 이동이었습니다. 결과적으로 버전 5는이 인터페이스를 제거했습니다.

또한 Spring Security는 인코딩 된 암호를 처리하는 방식을 변경합니다. 이전 버전에서는 각 응용 프로그램이 하나의 암호 인코딩 알고리즘 만 사용했습니다.

기본적으로 StandardPasswordEncoder가 처리했습니다. 인코딩에 SHA-256을 사용했습니다. 암호 인코더를 변경하여 다른 알고리즘으로 전환 할 수 있습니다. 하지만 우리의 애플리케이션은 정확히 하나의 알고리즘을 고수해야했습니다.

버전 5.0에는 암호 인코딩 위임 개념이 도입되었습니다. 이제 우리는 다른 암호에 다른 인코딩을 사용할 수 있습니다. Spring은 인코딩 된 암호를 접두사로하는 식별자로 알고리즘을 인식합니다.

다음은 bcrypt로 인코딩 된 비밀번호의 예입니다.

{bcrypt}$2b$12$FaLabMRystU4MLAasNOKb.HUElBAabuQdX59RWHq5X.9Ghm692NEi

맨 처음에 bcrypt가 중괄호로 지정되는 방식에 유의하십시오.

3. 위임 구성

암호 해시에 접두사가없는 경우 위임 프로세스는 기본 인코더를 사용합니다. 따라서 기본적으로 StandardPasswordEncoder를 얻습니다 .

따라서 이전 Spring Security 버전의 기본 구성과 호환됩니다.

버전 5에서 Spring Security는 PasswordEncoderFactories.createDelegatingPasswordEncoder ()를 도입했습니다 . 이 팩토리 메서드는 DelegationPasswordEncoder 의 구성된 인스턴스를 반환합니다 .

접두사가없는 암호의 경우 해당 인스턴스는 방금 언급 한 기본 동작을 보장합니다. 그리고 접두사가 포함 된 암호 해시의 경우 그에 따라 위임이 수행됩니다.

Spring Security 팀은 해당 JavaDoc 의 최신 버전에서 지원되는 알고리즘을 나열합니다 .

물론 Spring에서는이 동작을 구성 할 수 있습니다.

다음을 지원한다고 가정 해 보겠습니다.

  • 새로운 기본값으로 bcrypt
  • 대안으로 scrypt
  • 현재 사용되는 알고리즘으로 SHA-256.

이 설정의 구성은 다음과 같습니다.

@Bean
public PasswordEncoder delegatingPasswordEncoder() {
    PasswordEncoder defaultEncoder = new StandardPasswordEncoder();
    Map<String, PasswordEncoder> encoders = new HashMap<>();
    encoders.put("bcrypt", new BCryptPasswordEncoder());
    encoders.put("scrypt", new SCryptPasswordEncoder());

    DelegatingPasswordEncoder passworEncoder = new DelegatingPasswordEncoder(
      "bcrypt", encoders);
    passworEncoder.setDefaultPasswordEncoderForMatches(defaultEncoder);

    return passworEncoder;
}

4. 암호 인코딩 알고리즘 마이그레이션

이전 섹션에서는 필요에 따라 암호 인코딩을 구성하는 방법을 살펴 보았습니다. 따라서 이제 이미 인코딩 된 암호를 새 알고리즘으로 전환하는 방법에 대해 알아 봅니다.

인코딩을 SHA-256 에서 bcrypt 로 변경하고 싶지만 사용자가 암호 를 변경하는 것을 원하지 않는다고 가정 해 보겠습니다 .

한 가지 가능한 해결책은 로그인 요청을 사용하는 것입니다. 이 시점에서 일반 텍스트로 자격 증명에 액세스 할 수 있습니다. 이때 현재 비밀번호를 가져 와서 다시 인코딩 할 수 있습니다.

결과적으로 Spring의 AuthenticationSuccessEvent사용할 수 있습니다 . 이 이벤트는 사용자가 애플리케이션에 성공적으로 로그인 한 후에 발생합니다.

다음은 예제 코드입니다.

@Bean
public ApplicationListener<AuthenticationSuccessEvent>
  authenticationSuccessListener( PasswordEncoder encoder) {
    return (AuthenticationSuccessEvent event) -> {
        Authentication auth = event.getAuthentication();

        if (auth instanceof UsernamePasswordAuthenticationToken
          && auth.getCredentials() != null) {

            CharSequence clearTextPass = (CharSequence) auth.getCredentials();
            String newPasswordHash = encoder.encode(clearTextPass);

            // [...] Update user's password

            ((UsernamePasswordAuthenticationToken) auth).eraseCredentials();
        }
    };
}

이전 스 니펫에서 :

  • 제공된 인증 세부 정보에서 일반 텍스트로 사용자 암호를 검색했습니다.
  • 새 알고리즘으로 새 암호 해시를 만들었습니다.
  • 인증 토큰에서 일반 텍스트 암호를 제거했습니다.

기본적으로 Spring Security가 가능한 한 빨리 삭제하기 때문에 일반 텍스트로 비밀번호를 추출하는 것은 불가능합니다.

따라서 우리는 비밀번호의 일반 텍스트 버전을 유지하도록 Spring을 구성해야합니다.

또한 인코딩 위임을 등록해야합니다.

@Configuration
public class PasswordStorageWebSecurityConfigurer
  extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) 
      throws Exception {
        auth.eraseCredentials(false)
          .passwordEncoder(delegatingPasswordEncoder());
    }

    // ...
}

5. 결론

이 빠른 기사에서는 5.x에서 사용할 수있는 몇 가지 새로운 암호 인코딩 기능에 대해 설명했습니다.

또한 여러 암호 인코딩 알고리즘을 구성하여 암호를 인코딩하는 방법도 살펴 보았습니다. 또한 기존 암호를 깨지 않고 암호 인코딩을 변경하는 방법을 탐색했습니다.

마지막으로 Spring 이벤트를 사용하여 암호화 된 사용자 암호를 투명하게 업데이트하여 사용자에게 공개하지 않고도 인코딩 전략을 원활하게 변경할 수있는 방법을 설명했습니다.

마지막으로 항상 그렇듯이 모든 코드 예제는 GitHub 저장소 에서 사용할 수 있습니다 .