유튜브 "개발자 유미"님 강의를 듣고 정리한 내용입니다.
Bcrypt는 블로피시 암호에 기반을 둔 암호화 해시함수로서, 단방향 암호화를 위해서 만들어진 해시함수이다. SALT를 생성하여 암호에 덧붙여 레인보우 공격을 방지한다.(SALT는 SHA-256에서도 사용되기도 한다.) Bcrypt는 현재까지 사용되는 가장 강력한 암호화 매커니즘 중 하나이다.
단방향 암호화의 경우 양방향 암호화와는 달리 복호화가 불가능하다. 단방향 암호화를 통해서 password를 관리할 수 있다.
인증 시에는 사용자가 입력한 password를 단방향 암호화 기술로 암호화하여 DB에 저장된 것과 비교하여 인증할 수 있다.
만약 password DB가 유출되더라도, DB 내부에 원본 password 대신 암호화된 password를 저장해두면 복호화가 불가능하기 때문에 안전하다.
스프링 시큐리티에서도 앞서 말한 password의 대조와 관리를 위해 암호화를 진행해야 한다.
스프링 시큐리티에서는 Bcrypt Password Encoder를 제공하고, 권장한다. 따라서 해당 클래스를 Configuration 파일에 빈으로 등록하는 과정이 필요하다.
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder(){
return new BCryptPasswordEncoder();
}
Configuration 파일에 위와 같이 BcryptPasswordEnoder를 빈으로 등록하면 암호화를 위해 해당 빈을 사용할 수 있다.
회원 가입 서비스에서 비밀번호의 암호화를 위해 사용하게 된다. 다음과 같이 사용할 수 있다.
@Service
@RequiredArgsConstructor
public class JoinService {
private final UserRepository userRepository;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
public void joinProcess(JoinDto joinDto) {
// 중복 회원명 조회 로직
if(!userRepository.existsByUsername(joinDto.getUsername())){
return;
}
UserEntity userEntity = new UserEntity();
userEntity.setUsername(joinDto.getUsername());
// 비밀번호 DB 저장 시 bcrypt encoder 로 인코딩 후 저장
userEntity.setPassword(bCryptPasswordEncoder.encode(joinDto.getPassword()));
userEntity.setRole("ROLE_USER");
userRepository.save(userEntity);
}
}
먼저 빈으로 등록한 BcryptPasswordEncoder를 사용하기 위해 생성자 주입 방식으로 DI 시켰다.
그리고 리포지토리에 엔티티를 저장하기 전, 엔티티 객체의 password를 set 할 때 암호화를 시켰다. BcryptPasswordEncoder.encode() 메서드의 파라미터로 password를 넣어주면 SALT 값을 추가해 암호화 되어진 password가 리턴된다.
참고 : https://docs.spring.io/spring-security/reference/servlet/appendix/faq.html#appendix-faq-role-prefix
Role 설정 시, 접두사로 반드시 ROLE_을 붙여줘야 한다.
ex) ROLE_ADMIN, ROLE_USER
스프링 시큐리티는 voter 기반 아키텍쳐로, voter들은 configuration attributes 위에서 동작하며 이는 자원들을 보호하기 위함이다.(예시 : 메서드 호출, 서블릿 호출)
대표적인 voter로 RoleVoter가 있다. RoleVoter는 ROLE_ 접두사가 붙은 attribute를 찾아 권한을 줄 수 있는지 vote하게 된다. 그래서 DB에 저장하기 위해 엔티티에 역할을 부여할 때는 ROLE_ 접두사를 붙여서 주어야한다.