diff --git a/src/main/java/com/back/web7_9_codecrete_be/global/security/JwtAuthenticationFilter.java b/src/main/java/com/back/web7_9_codecrete_be/global/security/JwtAuthenticationFilter.java index 46c3038b..0ff683a0 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/global/security/JwtAuthenticationFilter.java +++ b/src/main/java/com/back/web7_9_codecrete_be/global/security/JwtAuthenticationFilter.java @@ -65,7 +65,8 @@ protected void doFilterInternal(HttpServletRequest request, SecurityContextHolder.getContext().setAuthentication(auth); } catch (BusinessException ex) { - // Refresh도 실패 → 익명 사용자 유지 + // 재발급 실패 시 SecurityContext 비우기 + SecurityContextHolder.clearContext(); log.debug("Access Token 재발급 실패: {}", ex.getErrorCode()); } diff --git a/src/main/java/com/back/web7_9_codecrete_be/global/security/SecurityConfig.java b/src/main/java/com/back/web7_9_codecrete_be/global/security/SecurityConfig.java index b88226c8..971f0e1a 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/global/security/SecurityConfig.java +++ b/src/main/java/com/back/web7_9_codecrete_be/global/security/SecurityConfig.java @@ -8,8 +8,13 @@ import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +import java.util.List; @Configuration @RequiredArgsConstructor @@ -36,6 +41,10 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti // H2 Console 설정 .headers(headers -> headers.frameOptions(frame -> frame.disable())) + // 세션 관리 설정 - Stateless + .sessionManagement((session) -> session + .sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + // Authorization 설정 .authorizeHttpRequests(auth -> auth .requestMatchers( @@ -45,6 +54,13 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti "/h2-console/**", // H2 Console "/api/v1/concerts/**" // concert 정보 조회 도메인 ).permitAll() + + // ADMIN 전용 + .requestMatchers("/api/v1/admin/**").hasRole("ADMIN") + + // USER, ADMIN 허용 + .requestMatchers("/api/v1/users/**").hasAnyRole("USER", "ADMIN") + .anyRequest().authenticated() ) @@ -60,4 +76,23 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception { return configuration.getAuthenticationManager(); } + + // CORS 설정(로컬 프론트 통신 허용) + @Bean + public UrlBasedCorsConfigurationSource corsConfigurationSource() { + CorsConfiguration configuration =new CorsConfiguration(); + + configuration.setAllowedOrigins(List.of("http://localhost:3000")); + configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS")); + + configuration.setAllowedHeaders(List.of("*")); + + //쿠키 자동으로 넘어가게 설정 + configuration.setAllowCredentials(true); + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/api/**", configuration); + + return source; + } }