[JWT 필터 및 보안 설정 개선] JwtTokenValidationFilter에서 불필요한 의존성을 제거하고, WebSecurity에서 공개 및 API 경로에 대한 SecurityFilterChain을 추가하여 인증 경로를 명확히 설정함. application.properties에서 허용 경로 설정을 제거하여 코드 정리.
This commit is contained in:
@@ -1,12 +1,10 @@
|
||||
package com.bio.bio_backend.global.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.bio.bio_backend.domain.base.member.dto.MemberDto;
|
||||
import com.bio.bio_backend.global.utils.HttpUtils;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
@@ -24,7 +22,7 @@ import com.bio.bio_backend.global.dto.ApiResponseDto;
|
||||
import com.bio.bio_backend.domain.base.member.service.MemberService;
|
||||
import com.bio.bio_backend.global.constants.ApiResponseCode;
|
||||
import com.bio.bio_backend.global.utils.JwtUtils;
|
||||
import com.bio.bio_backend.global.config.SecurityPathConfig;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@@ -35,16 +33,8 @@ public class JwtTokenValidationFilter extends OncePerRequestFilter {
|
||||
private final JwtUtils jwtUtils;
|
||||
private final HttpUtils httpUtils;
|
||||
private final MemberService memberService;
|
||||
private final Environment env;
|
||||
private final SecurityPathConfig securityPathConfig;
|
||||
|
||||
@Override
|
||||
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
|
||||
String path = request.getRequestURI();
|
||||
String contextPath = env.getProperty("server.servlet.context-path", "");
|
||||
|
||||
return securityPathConfig.isPermittedPath(path, contextPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
|
||||
|
||||
@@ -4,7 +4,8 @@ import com.bio.bio_backend.global.filter.JwtTokenIssuanceFilter;
|
||||
import com.bio.bio_backend.global.filter.JwtTokenValidationFilter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
@@ -23,7 +24,6 @@ import com.bio.bio_backend.domain.base.member.mapper.MemberMapper;
|
||||
import com.bio.bio_backend.global.exception.CustomAuthenticationFailureHandler;
|
||||
import com.bio.bio_backend.global.utils.JwtUtils;
|
||||
import com.bio.bio_backend.global.utils.HttpUtils;
|
||||
import com.bio.bio_backend.global.config.SecurityPathConfig;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Configuration
|
||||
@@ -35,12 +35,10 @@ public class WebSecurity {
|
||||
private final BCryptPasswordEncoder bCryptPasswordEncoder;
|
||||
private final JwtUtils jwtUtils;
|
||||
private final ObjectMapper objectMapper;
|
||||
private final Environment env;
|
||||
private final SecurityPathConfig securityPathConfig;
|
||||
private final HttpUtils httpUtils;
|
||||
private final MemberMapper memberMapper;
|
||||
|
||||
private JwtTokenIssuanceFilter getJwtTokenIssuanceFilter(AuthenticationManager authenticationManager) throws Exception {
|
||||
private JwtTokenIssuanceFilter getJwtTokenIssuanceFilter(AuthenticationManager authenticationManager) {
|
||||
JwtTokenIssuanceFilter filter = new JwtTokenIssuanceFilter(authenticationManager, jwtUtils, objectMapper, memberService, httpUtils, memberMapper);
|
||||
filter.setFilterProcessesUrl("/login");
|
||||
filter.setAuthenticationFailureHandler(new CustomAuthenticationFailureHandler(objectMapper));
|
||||
@@ -48,14 +46,62 @@ public class WebSecurity {
|
||||
}
|
||||
|
||||
private JwtTokenValidationFilter getJwtTokenValidationFilter() {
|
||||
return new JwtTokenValidationFilter(jwtUtils, httpUtils, memberService, env, securityPathConfig);
|
||||
return new JwtTokenValidationFilter(jwtUtils, httpUtils, memberService);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 공개 경로용 SecurityFilterChain (우선순위 1)
|
||||
*
|
||||
* 처리 경로:
|
||||
* - 인증 관련: /login, /logout, /members/register
|
||||
* - API 문서: /swagger-ui/**, /api-docs/**
|
||||
* - WebSocket: /ws/**
|
||||
* - 모니터링: /actuator/**
|
||||
*
|
||||
* 모든 경로는 인증 없이 접근 가능
|
||||
*/
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
@Order(1)
|
||||
SecurityFilterChain publicChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.securityMatcher(
|
||||
// 인증 관련 공개 경로
|
||||
"/logout", "/members/register",
|
||||
|
||||
// Swagger UI 관련 경로
|
||||
"/swagger-ui/**", "/swagger-ui.html", "/swagger-ui/index.html",
|
||||
|
||||
// API 문서 관련 경로
|
||||
"/api-docs", "/api-docs/**", "/v3/api-docs", "/v3/api-docs/**",
|
||||
|
||||
// WebSocket 관련 경로
|
||||
"/ws/**",
|
||||
|
||||
// Actuator 모니터링 경로
|
||||
"/actuator/**", "/actuator/health/**", "/actuator/info"
|
||||
)
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
.authorizeHttpRequests(auth -> auth.anyRequest().permitAll())
|
||||
.sessionManagement(session ->
|
||||
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||
);
|
||||
return http.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* API 경로용 SecurityFilterChain (우선순위 2)
|
||||
*
|
||||
* 처리 경로: publicChain에서 처리되지 않는 모든 경로
|
||||
* - 비즈니스 API 엔드포인트
|
||||
* - 사용자 데이터 관련 API
|
||||
* - 관리자 기능 API
|
||||
*
|
||||
* 모든 요청에 대해 JWT 토큰 인증 필수
|
||||
*/
|
||||
@Bean
|
||||
@Order(2)
|
||||
SecurityFilterChain apiChain(HttpSecurity http) throws Exception {
|
||||
// AuthenticationManager 설정
|
||||
AuthenticationManagerBuilder authenticationManagerBuilder =
|
||||
http.getSharedObject(AuthenticationManagerBuilder.class);
|
||||
@@ -63,25 +109,16 @@ public class WebSecurity {
|
||||
|
||||
AuthenticationManager authenticationManager = authenticationManagerBuilder.build();
|
||||
|
||||
// 설정 파일에서 허용할 경로 가져오기
|
||||
String[] permitAllPaths = securityPathConfig.getPermitAllPaths().toArray(new String[0]);
|
||||
|
||||
http.csrf(AbstractHttpConfigurer::disable) //csrf 비활성화
|
||||
.authorizeHttpRequests(request -> //request 허용 설정
|
||||
request
|
||||
.requestMatchers(permitAllPaths).permitAll() // 설정 파일에서 허용할 경로
|
||||
.anyRequest().authenticated() // 나머지 요청은 인증 필요
|
||||
)
|
||||
.authenticationManager(authenticationManager)
|
||||
.sessionManagement(session ->
|
||||
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 세션 사용 안함
|
||||
)
|
||||
.logout(AbstractHttpConfigurer::disable);
|
||||
http
|
||||
// 1단계: JWT 토큰 발급 필터 (로그인 요청 처리 및 토큰 발급)
|
||||
.addFilterBefore(getJwtTokenIssuanceFilter(authenticationManager), UsernamePasswordAuthenticationFilter.class)
|
||||
// 2단계: JWT 토큰 검증 필터 (자동 토큰 갱신 포함)
|
||||
.addFilterBefore(getJwtTokenValidationFilter(), UsernamePasswordAuthenticationFilter.class);
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
.authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
|
||||
.authenticationManager(authenticationManager)
|
||||
.sessionManagement(session ->
|
||||
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||
)
|
||||
.logout(AbstractHttpConfigurer::disable)
|
||||
.addFilterBefore(getJwtTokenIssuanceFilter(authenticationManager), UsernamePasswordAuthenticationFilter.class) // 토큰 발급
|
||||
.addFilterBefore(getJwtTokenValidationFilter(), UsernamePasswordAuthenticationFilter.class); // 토큰 검증
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@@ -114,10 +114,6 @@ springdoc.swagger-ui.disable-swagger-default-url=true
|
||||
springdoc.default-produces-media-type=application/json
|
||||
springdoc.default-consumes-media-type=application/json
|
||||
|
||||
# ========================================
|
||||
# 보안 설정 - 허용할 경로
|
||||
security.permit-all-paths=/login,/logout,/members/register,/swagger-ui/**,/swagger-ui.html,/swagger-ui/index.html,/api-docs,/api-docs/**,/v3/api-docs,/v3/api-docs/**,/ws/**,/actuator/**,/actuator/health/**,/actuator/info
|
||||
|
||||
# 파일 업로드 설정
|
||||
# ========================================
|
||||
spring.servlet.multipart.enabled=true
|
||||
|
||||
Reference in New Issue
Block a user