From 84ba9f070d0c29ad98954614ff7930b29e9002c5 Mon Sep 17 00:00:00 2001 From: csct3434 Date: Mon, 13 Nov 2023 07:17:48 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20CORS=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../alzzaipo/common/config/CorsConfig.java | 26 ++++++++ .../common/config/SecurityConfig.java | 63 ++----------------- .../com/alzzaipo/common/jwt/JwtFilter.java | 42 +++++++++---- 3 files changed, 61 insertions(+), 70 deletions(-) create mode 100644 src/main/java/com/alzzaipo/common/config/CorsConfig.java diff --git a/src/main/java/com/alzzaipo/common/config/CorsConfig.java b/src/main/java/com/alzzaipo/common/config/CorsConfig.java new file mode 100644 index 00000000..c7368b8e --- /dev/null +++ b/src/main/java/com/alzzaipo/common/config/CorsConfig.java @@ -0,0 +1,26 @@ +package com.alzzaipo.common.config; + +import java.util.List; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +@Configuration +public class CorsConfig { + + @Bean + public CorsConfigurationSource corsConfigurationSource() { + CorsConfiguration config = new CorsConfiguration(); + config.setAllowedOrigins(List.of("https://alzzaipo.com", "http://localhost:3000")); + config.addAllowedMethod("*"); + config.addAllowedHeader("*"); + config.setAllowCredentials(true); + config.addExposedHeader("Authorization"); + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", config); + return source; + } +} diff --git a/src/main/java/com/alzzaipo/common/config/SecurityConfig.java b/src/main/java/com/alzzaipo/common/config/SecurityConfig.java index f78a7214..40b41ddc 100644 --- a/src/main/java/com/alzzaipo/common/config/SecurityConfig.java +++ b/src/main/java/com/alzzaipo/common/config/SecurityConfig.java @@ -7,15 +7,9 @@ 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.annotation.web.configuration.WebSecurityCustomizer; -import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import org.springframework.web.cors.CorsConfiguration; -import org.springframework.web.cors.CorsConfigurationSource; -import org.springframework.web.cors.UrlBasedCorsConfigurationSource; - -import java.util.List; @RequiredArgsConstructor @EnableWebSecurity @@ -24,62 +18,13 @@ public class SecurityConfig { private final JwtUtil jwtUtil; - @Bean - public CorsConfigurationSource corsConfigurationSource() { - CorsConfiguration config = new CorsConfiguration(); - config.setAllowedOrigins(List.of("https://alzzaipo.com", "http://localhost:3000")); - config.addAllowedMethod("*"); - config.addAllowedHeader("*"); - config.setAllowCredentials(true); - config.addExposedHeader("Authorization"); - - UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); - source.registerCorsConfiguration("/**", config); - return source; - } - @Bean public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception { httpSecurity - .httpBasic().disable() - .csrf().disable() - .cors().and() - .authorizeHttpRequests(authorize -> authorize - .requestMatchers( - "/member/verify-account-id", - "/member/verify-email", - "/member/register", - "/member/login", - "/ipo/**", - "/email/**", - "/scraper", - "/oauth/kakao/login" - ).permitAll() - .requestMatchers( - "/portfolio/**", - "/member/**", - "/oauth/kakao/*", - "/notification/**" - ).authenticated() - ) - .sessionManagement(sessionManagement -> sessionManagement - .sessionCreationPolicy(SessionCreationPolicy.STATELESS) - ) - .addFilterBefore(new JwtFilter(jwtUtil), UsernamePasswordAuthenticationFilter.class); + .csrf(AbstractHttpConfigurer::disable) + .cors().and() + .addFilterBefore(new JwtFilter(jwtUtil), UsernamePasswordAuthenticationFilter.class); return httpSecurity.build(); } - - @Bean - public WebSecurityCustomizer webSecurityCustomizer() { - return web -> web.ignoring().requestMatchers( - "/member/verify-account-id", - "/member/verify-email", - "/member/register", - "/member/login", - "/ipo/**", - "/email/**", - "/scraper", - "/oauth/kakao/login"); - } } \ No newline at end of file diff --git a/src/main/java/com/alzzaipo/common/jwt/JwtFilter.java b/src/main/java/com/alzzaipo/common/jwt/JwtFilter.java index 1dc1d3a4..bbfd6d3d 100644 --- a/src/main/java/com/alzzaipo/common/jwt/JwtFilter.java +++ b/src/main/java/com/alzzaipo/common/jwt/JwtFilter.java @@ -7,6 +7,9 @@ import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpHeaders; @@ -16,9 +19,6 @@ import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.web.filter.OncePerRequestFilter; -import java.io.IOException; -import java.util.List; - @Slf4j @RequiredArgsConstructor public class JwtFilter extends OncePerRequestFilter { @@ -26,8 +26,9 @@ public class JwtFilter extends OncePerRequestFilter { private final JwtUtil jwtUtil; @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) - throws IOException, ServletException { + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, + FilterChain filterChain) + throws IOException, ServletException { String authorization = request.getHeader(HttpHeaders.AUTHORIZATION); @@ -42,11 +43,12 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse MemberPrincipal memberPrincipal = createPrincipalFromToken(token); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( - memberPrincipal, - null, - List.of(new SimpleGrantedAuthority("USER"))); + memberPrincipal, + null, + List.of(new SimpleGrantedAuthority("USER"))); - authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + authenticationToken.setDetails( + new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authenticationToken); } catch (ExpiredJwtException e) { response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "토큰 만료"); @@ -65,7 +67,25 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse private MemberPrincipal createPrincipalFromToken(String token) { return new MemberPrincipal( - jwtUtil.getMemberUID(token), - jwtUtil.getLoginType(token)); + jwtUtil.getMemberUID(token), + jwtUtil.getLoginType(token)); } + + @Override + protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { + List excludePath = Arrays.asList( + "/member/verify-account-id", + "/member/verify-email", + "/member/register", + "/member/login", + "/ipo/*", + "/email/*", + "/scraper", + "/oauth/kakao/login"); + + String path = request.getRequestURI(); + + return excludePath.stream().anyMatch(path::startsWith); + } + } From 77c1bd9aa467d2c38e578e0a9cc5c3fa08da777b Mon Sep 17 00:00:00 2001 From: csct3434 Date: Mon, 13 Nov 2023 07:32:06 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20URL=20=EA=B8=B0=EB=B0=98=20=ED=95=84?= =?UTF-8?q?=ED=84=B0=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit startsWith 메서드를 사용했기 때문에, 와일드 마스크를 사용하면 URL 기반 필터링이 제대로 동작하지 않는다. --- src/main/java/com/alzzaipo/common/jwt/JwtFilter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/alzzaipo/common/jwt/JwtFilter.java b/src/main/java/com/alzzaipo/common/jwt/JwtFilter.java index bbfd6d3d..d61fd224 100644 --- a/src/main/java/com/alzzaipo/common/jwt/JwtFilter.java +++ b/src/main/java/com/alzzaipo/common/jwt/JwtFilter.java @@ -78,8 +78,8 @@ protected boolean shouldNotFilter(HttpServletRequest request) throws ServletExce "/member/verify-email", "/member/register", "/member/login", - "/ipo/*", - "/email/*", + "/ipo", + "/email", "/scraper", "/oauth/kakao/login");