[ODOP] 94일차 - Form 인증 - 사용자 등록 : PasswordEncoder

[ODOP] 94일차 - Form 인증 - 사용자 등록 : PasswordEncoder

PasswordEncoder

  • 비밀번호를 안전하게 암호화 하도록 제공
  • Spring Security 5.0 이전에는 plain text 형식의 비밀번호도 저장이 가능했으나 해당 버전 이후는 암호화가 필수이다

생성

PasswordEncoder passwordEncoder = 
				PasswordEncoderFactories.createDelegatingPasswordEncoder()
  • 여러 암호화 전략을 지원하고 있으며 해당 전략은 PasswordEncoderFactories.createDelegatingPasswordEncoder() 의 코드에서 확인 할 수 있다

암호화 포맷 : {id}encodedPassword

  • 기본 포맷은 Bcrypt : {bcrypt}$2a$10$nmewYk/DMTtwnHuxLdpM2OCMFuhik8Uee01z99WdkvSsihOjHaHqy
  • 알고리즘 종류는 해당 함수 내부에서 확인가능하다

인터페이스

String encode(CharSequence rawPassword)

  • 원시 암호를 인코딩한다. 일반적으로 좋은 알고리즘은 무작위로 생성된 8바이트 이상의 SHA-1 이상의 해시 값을 솔트 하여 사용하는 것

boolean matches(CharSequence rawPassword, String encodedPassword)

  • 저장소에서 가져온 인코딩된 암호가 인코딩된 후 제출된 원시 암호와 일치하는지 확인.
    암호가 일치하면 true를 반환하고 일치하지 않으면 false를 반환.
    저장된 암호 자체는 디코딩되지 않는다.

해당 PasswordEncoder 를 통해 암호화 된 상태의 값은 이와 비슷하게 변화한다.

{bcrypt}$2a$10$JPP33eL3ePjHuG/ePTyc9Of37EvWP6DpVthbEdjpYifhMP2IHfW6C

보면 {bcrypt} 라는 키워드를 볼 수 있는데, 이는 암호화 하는데 사용한 기법을 구분하는데 사용됨.

  • 사용하는 passwordEncoder 는 spring bean 에 등록 되어 있어야 한다.
    키워드를 확인하여 등록되어 있지 않은 암호화가 사용되었다 판단 될 경우, 에러를 띄우기 때문.

암호화 사용

더 좋은 사용 방법이 있지만, 기본적인 것 부터 해보자.

package com.pollra.security.application.view.service;

import com.pollra.security.application.config.security.entity.Account;
import com.pollra.security.application.view.repository.AccountRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
@RequiredArgsConstructor
public class AccountService {

    private final AccountRepository accountRepository;
    private final PasswordEncoder passwordEncoder;

    public Account add(Account account) {
        String encodePassword = passwordEncoder.encode(account.getPassword());
        account.setPassword(encodePassword);
        return accountRepository.save(account);
    }
}

의존성 주입 받은 PasswordEncoder 는 다음의 형태로 Bean 등록

import org.springframework.context.annotation.Bean;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;

...

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

다음은 해당 코드 구성을 통해 실제로 암호화된 데이터의 결과