Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
Tags
- multi-threading
- function
- 인텔리제이 기초 설정
- Java
- 집합관계
- 포함관계
- 형 변환
- 자바 멀티스레딩
- Thread
- JAVA기초
- 연관관계
- 메서드
- 메서드 오버로딩
- 접근제어지시자
- 컴파일
- for문
- 반복문
- Java데이터 타입
- OPP개념
- continue문
- 상수
- break문
- IntelliJ IDEA
- this예약어
- java변수
- 생성자
- 인텔리제이 한글 깨짐 해결법
- While
- JAVA객체지향
- 시스템 환경 변수 편집
Archives
- Today
- Total
최원종의 개발 블로그
V13 비밀번호 암호화 (회원 가입시 암호화 처리 ) 본문
build.gradle
dependencies {
// ... 기존 의존성 ...
// 암호화
implementation 'org.springframework.security:spring-security-crypto'
// ... 기존 의존성 ...
}
- Spring Security Crypto 모듈은 Spring Security의 일부이지만,
전체 Spring Security를 사용하지 않고 암호화 기능만 사용할 수 있습니다.
- BCryptPasswordEncoder를 사용하기 위한 최소한의 의존성입니다.
WebMvcConfig 메서드로 IoC 처리 - PasswordEncoder
package com.tenco.blog._core.config;
import com.tenco.blog._core.interceptor.AdminInterceptor;
import com.tenco.blog._core.interceptor.LoginInterceptor;
import com.tenco.blog._core.interceptor.SessionInterceptor;
import com.tenco.blog._core.util.FileUtil;
import lombok.RequiredArgsConstructor;
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.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.nio.file.Paths;
// 자바 코드로 스프링 부트 설정 파일을 다둘 수 있다.
// @Component
@Configuration // IoC 대상 - 하나 이상의 IoC 처리를 하고 싶을 때 사용 한다.
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired // DI 처리
private LoginInterceptor loginInterceptor;
@Autowired // DI 처리
private SessionInterceptor sessionInterceptor;
@Autowired
private AdminInterceptor adminInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 화면에 SessionUser 정보를 내려줄 사용 됨.
registry.addInterceptor(sessionInterceptor)
.addPathPatterns("/**"); // 모든 URL 요청서 동작 함
// 인증 처리 인터셉터 동작 함
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/board/**", "/user/**", "/reply/**", "/admin/**")
.excludePathPatterns(
// 로그인 관련(인증이 필요 없는 페이지)
"/login-form", // 로그인 화면 요청 시
"/join-form", // 회원 가입 화면 요청 시
"/logout", // 로그아웃
// 게시글 조회 관련 (인증 없이도 볼 수 있는 페이지)
"/board/list", // 게시글 목록 화면 요청 시
"/" , // 메인 페이지
"/index" , // 메인 페이지
"/board/{id:\\d+}", // 게시글 상세보기( 숫자 ID만 허용)
// 정적 리소스 (CSS, JS, 이미지 등)
"/css/**", // CSS 파일 제외
"/js/**", // JS 파일 제외
"/images/**", // 이미지 파일 제외
"/favicon.ico", // 파비콘 제외
// H2 데이터베시스 콘솔( 개발 환경용)
"/h2-console/**" // H2 콘솔 접근
);
// 관리자 페이지 요청이 들어 왔을 때 1단계 로그인 여부 확인, 2단계 Role 확인해서
// ADMIN 일 경우만 관리자 페이지로 이동 가능하게 처리
registry.addInterceptor(adminInterceptor).addPathPatterns("/admin/**");
}
// 정적 리소스 핸들러 설정
// 외부 사용자가 내 서버 컴퓨터에 특정 경로를 바로 확인을 할 수 있게 한다면
// 보안상 취약 할 수 있습니다. ( 사용자에게는 가짜 경로를 보여주고 내부에서는
// 실정 경로를 찾을 수 있도록 처리 하는 기법(보안상)
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String externalPath = Paths.get(FileUtil.IMAGES_DIR).toString();
registry.addResourceHandler("/images/**")
// file: 추가 하기
.addResourceLocations("file:" + externalPath);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
UserService 회원가입시 평문을 암호화 처리해서 저장
/**
* 회원 가입 처리
* @param joinDTO (사용자 회원가입 요청 정보)
* @return User (저장된 사용자 정보)
*/
@Transactional
public User 회원가입(UserRequest.JoinDTO joinDTO) {
log.info("회원가입 서비스 시작");
// 회원가입시 사용자 이름 중복 체크
userRepository.findByUsername(joinDTO.getUsername()).ifPresent(user -> {
log.warn("회원가입 실패 - 중복된 사용자명 : {}", user.getUsername());
throw new Exception400("이미 존재하는 사용자 이름입니다");
});
// 프로필 이미지 저장 기능 구현 (선택 사항 임)
String profileImageFilename = null;
if(joinDTO.getProfileImage() != null && joinDTO.getProfileImage().isEmpty() == false) {
try {
// 이미지 파일이 맞는지 검증
if(FileUtil.isImageFile(joinDTO.getProfileImage()) == false) {
throw new Exception400("이미지 파일만 업로드 가능합니다");
}
profileImageFilename = FileUtil.saveFile(joinDTO.getProfileImage(), FileUtil.IMAGES_DIR);
} catch (Exception e) {
// 디스크 공간 없거나, 권한 없음
throw new Exception500("프로필 이미지 저장 실패");
}
}
// 코드 수정
User user = joinDTO.toEntity(profileImageFilename);
String hashPwd = passwordEncoder.encode(joinDTO.getPassword());
System.out.println("rawPwd " + joinDTO.getPassword());
System.out.println("hashPwd " + hashPwd);
user.setPassword(hashPwd);
// 기본 권한 추가 (일반 사용자로 설정)
user.addRole(Role.USER);
return userRepository.save(user);
}

'Spring boot 입문' 카테고리의 다른 글
| V13-3 회원 가입시 출처 관리 (로컬, 소셜) (0) | 2026.06.02 |
|---|---|
| V13-2 로그인시 메서드 수정(암호화 처리) (0) | 2026.06.02 |
| V12 - 2 카카오 소셜 로그인 (0) | 2026.05.26 |
| V12-1 Oauth 2.0 (카카오 소셜 로그인) (0) | 2026.05.26 |
| V11 - 2 역할 기반 접근 제어 (0) | 2026.05.26 |
