개요
Spring Security 6 + JWT 로그인, 로그아웃 과정의 두번째 글인 global 패키지에 대한 글이다.
파일 구조
/src/main/java/project
├── global
│ ├── config
│ │ └── security
│ │ └── SecurityConfig.java
│ └── entity
│ └── AuditingFields.java
├── jwt
│ ├── entity
│ │ └── Token.java
│ ├── filter
│ │ └── TokenAuthenticationFilter.java
│ ├── infrastructure
│ │ ├── CustomUserDetails.java
│ │ └── JwtAuthenticationToken.java
│ ├── repository
│ │ └── TokenRepository.java
│ ├── service
│ │ ├── CustomUserDetailsService.java
│ │ └── TokenService.java
│ └── util
│ └── JwtTokenizer.java
└── user
├── controller
│ └── UserController.java
├── dto
│ ├── UserJoinDto.java
│ ├── UserLoginDto.java
│ └── UserLoginResponseDto.java
├── entity
│ ├── Authority.java
│ └── User.java
├── repository
│ └── UserRepository.java
└── service
└── UserService.java
SecurityConfig.java
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
/**
* Spring Security 설정 클래스
* 애플리케이션의 보안 구성을 정의
*/
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
// JWT util
private final JwtTokenizer jwtTokenizer;
// 모든 유저 허용 페이지
String[] allAllowPage = new String[]{
"/", // 메인페이지
"/error", // 에러페이지
"/test/**", // 테스트 페이지
"/user/refreshToken" // 토큰 재발급 페이지
};
// 비로그인 유저 허용 페이지
String[] notLoggedAllowPage = new String[]{
"/user/login", // 로그인 페이지
"/user/join" // 회원가입 페이지
};
/**
* 보안 필터 체인
*
* @param http 수정할 HttpSecurity 객체
* @return 구성된 SecurityFilterChain
* @throws Exception HttpSecurity 구성 시 발생한 예외
*/
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// 유저별 페이지 접근 허용
http.authorizeHttpRequests(auth -> auth
.requestMatchers(allAllowPage).permitAll() // 모든 유저
.requestMatchers(notLoggedAllowPage).not().authenticated() // 비로그인 유저
.anyRequest().authenticated()
);
// 세션 관리 Stateless 설정(서버가 클라이언트 상태 저장x)
http.sessionManagement(auth -> auth.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
// cors 허용
http.csrf(csrf -> csrf.disable());
// 로그인 폼 비활성화
http.formLogin(auth -> auth.disable());
// http 기본 인증(헤더) 비활성화
http.httpBasic(auth -> auth.disable());
// JWT 필터 사용
http.addFilterBefore(new TokenAuthenticationFilter(jwtTokenizer), UsernamePasswordAuthenticationFilter.class);
// SecurityFilterChain을 빌드 후 반환
return http.build();
}
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}
AuditingFields.java
import jakarta.persistence.Column;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
import lombok.ToString;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
/**
* create, modify date 추상 클래스
*/
@ToString
@Getter
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
public abstract class AuditingFields {
/**
* create_date 엔티티 생성 시 자동 생성, 수정 불가
*/
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@CreatedDate
@Column(nullable = false, updatable = false)
protected LocalDateTime createDate;
/**
* modify_date 엔티티 수정 시 자동 업데이트
*/
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@LastModifiedDate
@Column(nullable = false)
protected LocalDateTime modifyDate;
}
이전 글
다음 글