-
Spring boot + React 시작하기 4 (비밀번호 암호화하여 DB에 적재하기 Spring Security)DEV/spring 2024. 2. 19. 18:12
이 전에 작성한 코드의 경우 유저(client)에게 받아온 password를 그대로 database에 저장했다.
당연하게도 비밀번호를 그대로 저장하는 서비스는 존재하지 않는다.
Springframework의 security를 이용하여 client로 부터 받아온 password를 암호화하여 db에 저장하도록 수정해 보자.
이 전 시리즈를 보지 않았다면 그 전 코드를 참고하자. (해당 게시물 최하단에 링크를 걸어두었다.)
해당 환경에 대한 정보는해당 시리즈 1편[1]을 참고하자.
환경 : Mac OS, JDK17, Gradle, Spring 3.2.2
1. 의존성 주입
SpringFramework의 Security를 사용하기 위해 의존성을 주입하자.
(gradle에 security를 추가하고 Gradle Reload하자.
build.gradle
// ...생략 dependencies { //... 생략 // security implementation 'org.springframework.boot:spring-boot-starter-security' } // ...생략
2. SecurityConfig 작성
WebSecurityConfig.java 신규 작성하자.
Security 폴더에 넣을...까...? WebSecurityConfig.java
package com.ssg.demo.v2.ssgdemov2; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; @Configuration @EnableWebSecurity public class WebSecurityConfig { @Bean // 어떠한 url로 진입을 해도 로그인 페이지로 인도 SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http // 403, "http.csrf.disable()" deprecated .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests((authorizeHttpRequests) -> authorizeHttpRequests // HTTP 요청에 대한 권한 설정, 모든 경로로 지정("/**") // permitAll() : 해당 요청에 대한 모든 사용자에게 접근 권한 부여 .requestMatchers(new AntPathRequestMatcher("/**")).permitAll() ); return http.build(); } @Bean // BCryptPasswordEncoder의 interface PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean // Spring 보안 및 인증 담당 AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception { return authenticationConfiguration.getAuthenticationManager(); } }
3. AuthService.java 수정
암호를 database에 저장하는 순간은 현재 본인의 개발 환경 기준으로 회원가입, 로그인(일반 로그인, 관리자 로그인)이다.
결국 중요한 부분(암호화)은 단 한곳이다.
// 사용자가 입력한 비밀번호를 BCryptPasswordEncoder를 사용하여 암호화 BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); String encodedPassword = userEntity.getPassword(); // 저장된 암호화된 비밀번호와 입력된 암호화된 비밀번호 비교 if(!passwordEncoder.matches(password, encodedPassword)) { return ResponseDto.setFailed("비밀번호가 일치하지 않습니다."); }
흐름을 파악하기 위해 하단 코드를 참고하자.
(특정 부분 명칭 그리고 코드가 수정되었다. 이점 참고하자. 기능은 동일하다.)
AuthService.java
//...생략 public ResponseDto<?> signUp(SignUpDto dto) { String email = dto.getEmail(); String password = dto.getPassword(); String confirmPassword = dto.getConfirmPassword(); // email(id) 중복 확인 try { // 존재하는 경우 : true / 존재하지 않는 경우 : false if(userRepository.existsById(email)) { return ResponseDto.setFailed("중복된 Email 입니다."); } } catch (Exception e) { return ResponseDto.setFailed("데이터베이스 연결에 실패하였습니다."); } // password 중복 확인 if(!password.equals(confirmPassword)) { return ResponseDto.setFailed("비밀번호가 일치하지 않습니다."); } // UserEntity 생성 UserEntity userEntity = new UserEntity(dto); // 비밀번호 암호화 BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); String hashedPassword = passwordEncoder.encode(password); boolean isPasswordMatch = passwordEncoder.matches(password, hashedPassword); if(!isPasswordMatch) { return ResponseDto.setFailed("암호화에 실패하였습니다."); } userEntity.setPassword(hashedPassword); // UserRepository를 이용하여 DB에 Entity 저장 try { userRepository.save(userEntity); } catch (Exception e) { return ResponseDto.setFailed("데이터베이스 연결에 실패하였습니다."); } return ResponseDto.setSuccess("회원 생성에 성공했습니다."); } public ResponseDto<SignInResponseDto> signIn(SignInDto dto) { String email = dto.getEmail(); String password = dto.getPassword(); UserEntity userEntity; try { // 이메일로 사용자 정보 가져오기 userEntity = userRepository.findById(email).orElse(null); if(userEntity == null) { return ResponseDto.setFailed("입력하신 이메일로 등록된 계정이 존재하지 않습니다."); } // 사용자가 입력한 비밀번호를 BCryptPasswordEncoder를 사용하여 암호화 BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); String encodedPassword = userEntity.getPassword(); // 저장된 암호화된 비밀번호와 입력된 암호화된 비밀번호 비교 if(!passwordEncoder.matches(password, encodedPassword)) { return ResponseDto.setFailed("비밀번호가 일치하지 않습니다."); } } catch (Exception e) { return ResponseDto.setFailed("데이터베이스 연결에 실패하였습니다."); } // Client에 비밀번호 제공 방지 userEntity.setPassword(""); String name = userEntity.getName(); //...코드 생략 return ResponseDto.setSuccessData("로그인에 성공하였습니다.", loginResponseDto); }
계정 생성 후 Database의 User 테이블을 확인하자.
비밀번호가 암호화되어 저장되었으며 로그인 및 계정 생성이 정상적으로 이루어 짐을 알 수 있다.
(참고로 DB에서 직접 밀어넣으면 당연히 안된다...)
기존에는 Access Token(JWT)만 생성하고 아직 토큰을 사용하지 않았다.
다음 게시물에서는 Refresh Token을 추가로 생성하고 두 토큰 이용 방법에 대해 작성할 예정이다.
Ref.
[1]. Spring boot + React 시작하기 1 (로그인 및 회원가입, 회원 관리 만들기) - 기본설정
https://seokbong.tistory.com/246
Spring boot + React 시작하기 1 (로그인 및 회원가입, 회원 관리 만들기) - 기본설정
연습용 프로젝트를 생성하면서 Sample로 진행 내역을 남겨봄 연습용 프로젝트는 Spring boot + React로 로그인 / 회원가입 및 회원관리 페이지를 만들어 보려고 한다. 개발 환경은 M1 Mac Os, Spring boot, Reac
seokbong.tistory.com
[2]. Spring boot + React 시작하기 2 (로그인 및 회원가입, 회원 관리 만들기) - 회원 가입
https://seokbong.tistory.com/247
Spring boot + React 시작하기 2 (로그인 및 회원가입, 회원 관리 만들기) - 회원 가입
1. Spring boot + React 시작하기 1 (로그인 및 회원가입, 회원 관리 만들기) - 기본설정 https://seokbong.tistory.com/246 Spring boot + React 시작하기 1 (로그인 및 회원가입, 회원 관리 만들기) 연습용 프로젝트를
seokbong.tistory.com
[3]. Spring boot + React 시작하기 3 (로그인 및 회원가입, 회원 관리 만들기) - 로그인 + 토큰생성
https://seokbong.tistory.com/248
Spring boot + React 시작하기 3 (로그인 및 회원가입, 회원 관리 만들기) - 로그인 + 토큰생성
1. Spring boot + React 시작하기 1 (로그인 및 회원가입, 회원 관리 만들기) - 기본설정 https://seokbong.tistory.com/246 Spring boot + React 시작하기 1 (로그인 및 회원가입, 회원 관리 만들기) - 기본설정 연습용
seokbong.tistory.com
'DEV > spring' 카테고리의 다른 글
Spring jakarta 의존성 주입 (0) 2024.02.20 Spring Security 적용 후 403 에러... 그리고 "http.csrf.disable()" deprecated (0) 2024.02.19 Spring boot + React 시작하기 3 (로그인 및 회원가입, 회원 관리 만들기) - 로그인 + 토큰생성 (0) 2024.02.13 Spring boot + React 시작하기 2 (로그인 및 회원가입, 회원 관리 만들기) - 회원 가입 (1) 2024.02.06 Spring boot + React 시작하기 1 (로그인 및 회원가입, 회원 관리 만들기) - 기본설정 (0) 2024.02.01