-

[스프링부트 및 JPA] - BCryptPasswordEncoder를 이용한 비밀번호 해시화 본문

백엔드 기술 정리/스프링 부트

[스프링부트 및 JPA] - BCryptPasswordEncoder를 이용한 비밀번호 해시화

흣차 2022. 2. 5. 01:36
728x90
반응형

지난 시간엔 비밀번호를 DB에 넣을 때 그대로 넣으면 문제가 생길 수 있기 때문에 암호화해서 DB에 넣는 작업을 해보겠습니다.

우선AuthService로 이동합니다. 

이후 

회원가입 메서드 위에 @Transactional을 달아줍니다.

이것을 걸면 함수가 실행되고 종료될 때까지 트랜잭션 관리를 스프링부트가 지원합니다.

보통은 이 트랜잭션을 Write할 때 사용하는데 우리는 Insert, Update, Delete할 때 사용하겠습니다.

왜냐하면 정보처리기사 관련 자격증을 공부해보신 분들이나 제 블로그에 있는 운영체제 포스팅을 읽으신 분은 이해하시겠지만 데이터를 Write할 때에는 그 어떤 사용자도 간섭해서는 안됩니다.

스프링부트에서는 다른 사용자가 접근하여 DB를 수정할 수 있기 때문에 @Transactional 어노테이션을 이용하여 메서드의 실행부터 종료까지 보호하는 역할을 지원합니다.

그러므로 데이터를 읽거나 쓰거나 지우는 작업을 할 때에는 반드시 트랜잭션 어노테이션을 이용해야 합니다.

그럼 본격적으로 암호화를 해봅시다.

SecurityConfig로 가서

요렇게 입력합니다.

이렇게 하면 encode()라는 메서드를 실행할 때 새로운 BCryptPasswordEncoder()를 생성해서 return합니다.

그리고 위에 @Bean어노테이션을 붙혔는데, 이를 통해 SecurityConfig가 IoC에 등록될 때 이 @Bean어노테이션을 읽어서 BCryptPasswordEncoder를 읽고 return하여 IoC에서 들고 있습니다.

 

 

다시 AuthService로 이동하겠습니다.

userRepository밑에 이렇게 DI로 불러오게끔 합니다.

@Bean메서드의 설명을 잘 보시면

Indicates that a method produces a bean to be managed by the Spring container.

이렇게 나와 있습니다.

메서드가 스프링컨테이너에 의해 관리되는 하나의 빈을 생성할 수 있게 도와준다고 해석할 수 있는데(영어 실력 ㅎㅎ ㅈㅅ) 이 어노테이션을 이용하면 메서드의 생성을 IoC에 등록하여 관리하도록 도울 수 있습니다.

지난 포스팅에서 UserRepository를 DI했을 땐 Bean을 이용 하지 않았던 것은 UserRepository가 메서드가 아니기 때문에 그렇습니다. (헷갈릴까봐 설명합니다.)

UserRepository는 클래스 단위의 DI 이용을 위해 JPAReposity를 상속했고 @RequiredArgsConstructor 어노테이션을 활용하여 final을 붙인 뒤 DI를 이용했던 것이고

BCryptPasswordEncoder는 메서드 단위의 실행을 위해 DI에 등록하기 위하여 @RequiredArgsConstructor 어노테이션을 활용하여 final을 붙인 것입니다.

그러므로 User-는 따로 빈등록을 하지 않고 JPA-를 상속받음으로써 자동으로 IoC에 등록할 수 있지만 BCr-는 메서드 등록을 위해 따로 빈 등록을 해야만 하는 것입니다.

실제로 회원가입을 위해 BCryptPasswordEncoder를 그대로 이용한 것이 아니라 우리는 encode메서드를 활용할 것입니다. 잘 확인하셨으면 좋겠습니다.

이렇게 입력해봅시다.

rawPassword는 user에서 getPassword하여 (원래의 pw를 가져와서)

encPassword는 bCryptPasswordEncoder에서 encode함수에 rawPassword를 넣고 돌린 암호화된 PW이고

user의 .setPassword(encPassword)는 user의 PW를 encPassword로 설정하겠단 뜻이고

마지막으로 User의 setRole -> 권한을 설정할건데, "ROLE_USER"라고 설정하겠단 뜻입니다.

(관리자는 ROLE_ADMIN으로 할 예정입니다.)

 

자 그런데 문제가 하나 생깁니다.

똑같은 username으로 아이디를 생성해도 그대로 회원가입이 된다는 점입니다.

(pw는 암호화가 성공적으로 완료된 것을 알 수 있습니다.)

그래서 제약조건을 하나 걸어줘야 하는데, User 클래스로 이동해봅시다.

username의 @Column에서 unique = true라고 설정해줍시다.

이렇게 하면 username은 오직 unique하게 설정할 수 있습니다.

근데 여기서 끝난게 아닙니다.

application.yml로 가서 ddl-auto를 create로 하여 실행했다가 다시 update로 바꾸고 해보시기 바랍니다.

그래야 확인할 수 있습니다.

실제로 그런지 봤더니 정말로 그렇네요.

unique 제약조건에 위배되었다고 나오네요!

즉, username이 중복이 되어 들어갔기 때문에 500오류가 났다고 해석할 수 있습니다.

그런데 사용자 입장에서는 username이 기존에 있는지 확인할 수단이 없기 때문에 만약 이런 오류 페이지가 뜬다면 굉장히 화가나서 회원가입하다가 사이트를 꺼버릴 수도 있습니다.

그럼 안되겠죠???

회원가입할 때 ID중복체크하는 것도 바로 이러한 이유때문에 그렇습니다.

회원가입 다 할 때 되어서야 오류가 뜨면 상당히 곤란하기 때문입니다.

그러므로 다음 포스팅에는 username의 중복확인을 미리 오류페이지를 띄우지 않고 사용자에게 알려주는 전처리 기법에 대해 알아보겠습니다.

감사합니다.

728x90
반응형
Comments