- [Springboot] 32. 사용자 비밀번호 암호화 처리2024년 08월 13일
- Song hyun
- 작성자
- 2024.08.13.:36
728x90반응형[Springboot] 32. 사용자 비밀번호 암호화 처리
1. SpringSecurityCrypto 의존성 추가
*Spring Security Crypto란?
-build.gradle 코드 수정
// 암호화 implementation 'org.springframework.security:spring-security-crypto'
plugins { id 'java' id 'war' id 'org.springframework.boot' version '3.2.8' id 'io.spring.dependency-management' version '1.1.6' } group = 'com.example' version = '0.0.1-SNAPSHOT' java { toolchain { languageVersion = JavaLanguageVersion.of(21) } } configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { // 의존성 추가 implementation 'org.apache.tomcat.embed:tomcat-embed-jasper' implementation group: 'org.glassfish.web', name: 'jakarta.servlet.jsp.jstl', version: '3.0.0' // TODO - check providedCompile 'javax.servlet:javax.servlet-api:3.1.0' // 암호화 implementation 'org.springframework.security:spring-security-crypto' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'com.h2database:h2' runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok' providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.3' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } tasks.named('test') { useJUnitPlatform() }
2. 사용자 비밀번호 암호화 처리
(1) WebMvcConfig
@Bean // IOC 대상 PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
package com.tenco.bank.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Component; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import com.tenco.bank.handler.AuthIntercepter; import lombok.RequiredArgsConstructor; @Configuration // <-- 하나의 클래스를 IOC 하고 싶다면 사용 @RequiredArgsConstructor public class WebMvcConfig implements WebMvcConfigurer { @Autowired // DI private final AuthIntercepter authIntercepter; // @RequiredArgsConstructor <-- 생성자 대신 사용 가능! // 우리가 만든 AuthIntercepter를 등록해야 한다. @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(authIntercepter) .addPathPatterns("/account/**") .addPathPatterns("/auth/**"); } @Bean // IOC 대상 PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
(2) UserService 구상
package com.tenco.bank.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.http.HttpStatus; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.tenco.bank.dto.SignInDTO; import com.tenco.bank.dto.SignUpDTO; import com.tenco.bank.handler.exception.DataDeliveryException; import com.tenco.bank.handler.exception.RedirectException; import com.tenco.bank.repository.interfaces.UserRepository; import com.tenco.bank.repository.model.User; import lombok.RequiredArgsConstructor; @Service // IoC 대상( 싱글톤으로 관리) @RequiredArgsConstructor public class UserService { @Autowired private final UserRepository userRepository; @Autowired private final PasswordEncoder passwordEncoder; /** * 회원 등록 서비스 기능 * 트랜잭션 처리 * @param dto */ @Transactional // 트랜잭션 처리는 반드시 습관화 public void createUser(SignUpDTO dto) { int result = 0; try { // 코드 추가 부분 // 회원 가입 요청 시, 사용자가 던진 비밀번호 값을 암호화처리 해야함 String hashpwd = passwordEncoder.encode(dto.getPassword()); System.out.println("암호화 확인: "+hashpwd); dto.setPassword(hashpwd); result = userRepository.insert(dto.toUser()); } catch (DataAccessException e) { throw new DataDeliveryException("중복 이름을 사용할 수 없습니다.", HttpStatus.INTERNAL_SERVER_ERROR); } catch (Exception e) { throw new RedirectException("알 수 없는 오류", HttpStatus.SERVICE_UNAVAILABLE); } if(result != 1) { throw new DataDeliveryException("회원가입 실패", HttpStatus.INTERNAL_SERVER_ERROR); } }
public User readUser(SignInDTO dto) { // 유효성 검사는 Controller 에서 먼저 하자. User userEntity = null; // 지역 변수 선언 // 기능 수정 // username만 가지고 select 처리하기 // 2가지의 경우의 수 --> 있거나. 없거나 // 객체 안에 사용자의 password가 존재한다. (암호화된 값) // passworEncoder 안에 매치하는 메서드 존재 => matches 메서드 try { userEntity = userRepository.findByUsernameAndPassword(dto.getUsername(), dto.getPassword()); } catch (DataAccessException e) { throw new DataDeliveryException("잘못된 처리 입니다.", HttpStatus.INTERNAL_SERVER_ERROR); } catch (Exception e) { throw new RedirectException("알수 없는 오류", HttpStatus.SERVICE_UNAVAILABLE); } if(userEntity == null) { throw new DataDeliveryException("아이디 혹은 비밀번호가 틀렸습니다.", HttpStatus.BAD_REQUEST); } return userEntity; }
3. 비밀번호-암호화된 비밀번호 매칭을 위한 메서드
(1) xml / repository 수정
public User findByUsername(@Param("username") String username);
<select id="findByUsername" resultType="com.tenco.bank.repository.model.User" > select * from user_tb where username = #{username} </select>
(2) UserService 수정
public User readUser(SignInDTO dto) { // 유효성 검사는 Controller 에서 먼저 하자. User userEntity = null; // 지역 변수 선언 // 기능 수정 // username만 가지고 select 처리하기 // 2가지의 경우의 수 --> 있거나. 없거나 // 객체 안에 사용자의 password가 존재한다. (암호화된 값) // passworEncoder 안에 매치하는 메서드 존재 => matches 메서드 try { userEntity = userRepository.findByUsername(dto.getUsername()); } catch (DataAccessException e) { throw new DataDeliveryException("잘못된 처리 입니다.", HttpStatus.INTERNAL_SERVER_ERROR); } catch (Exception e) { throw new RedirectException("알수 없는 오류", HttpStatus.SERVICE_UNAVAILABLE); } if(userEntity == null) { throw new DataDeliveryException("아이디 혹은 비밀번호가 틀렸습니다.", HttpStatus.BAD_REQUEST); } boolean isPwdMatched = passwordEncoder.matches(dto.getPassword(), userEntity.getPassword()); if(isPwdMatched == false) { throw new DataDeliveryException("비밀번호가 틀렸습니다.", HttpStatus.BAD_REQUEST); } return userEntity; }
728x90반응형'Springboot' 카테고리의 다른 글
[Springboot] 34. 파일 업로드(2단계-DTO, Service, JSP 수정) (0) 2024.08.13 [Springboot] 33. 파일 업로드(1단계-멀티 파트란?) (0) 2024.08.13 [Springboot] 31. DB 마이그레이션 (H2->MySQL) (0) 2024.08.13 [Springboot] 30. Intercepter 활용 (인증검사 공통 처리) (0) 2024.08.13 [Springboot] 29. 계좌 상세 보기 기능(5단계-계좌 목록 페이징 처리) (0) 2024.08.12 다음글이전글이전 글이 없습니다.댓글
스킨 업데이트 안내
현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)