Skip to content

Commit

Permalink
hotfix: CorsFilter 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
Shin-Jae-Yoon committed Nov 24, 2023
1 parent aedcd68 commit 9e35528
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 26 deletions.
73 changes: 73 additions & 0 deletions src/main/java/com/moabam/global/auth/filter/CorsFilter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.moabam.global.auth.filter;

import java.io.IOException;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.servlet.HandlerExceptionResolver;

import com.google.cloud.storage.HttpMethod;
import com.moabam.global.error.exception.UnauthorizedException;
import com.moabam.global.error.model.ErrorMessage;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Order(0)
@Component
@RequiredArgsConstructor
public class CorsFilter extends OncePerRequestFilter {

private static final String ALLOWED_METHOD_NAMES = "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH";
private static final String ALLOWED_HEADERS = "Origin, Accept, Access-Control-Request-Method, "
+ "Access-Control-Request-Headers, X-Requested-With,Content-Type, Referer";

private final HandlerExceptionResolver handlerExceptionResolver;

@Value("${allow}")
private String allowOrigin;

@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
FilterChain filterChain) throws ServletException, IOException {

try {
if (!secureMatch(httpServletRequest, allowOrigin)) {
throw new UnauthorizedException(ErrorMessage.INVALID_REQUEST_URL);
}
} catch (UnauthorizedException unauthorizedException) {
log.error("{}, {}", httpServletRequest.getHeader("referer"), allowOrigin);
handlerExceptionResolver.resolveException(httpServletRequest, httpServletResponse, null,
unauthorizedException);

return;
}

httpServletResponse.setHeader("Access-Control-Allow-Origin", allowOrigin);
httpServletResponse.setHeader("Access-Control-Allow-Methods", ALLOWED_METHOD_NAMES);
httpServletResponse.setHeader("Access-Control-Allow-Headers", ALLOWED_HEADERS);
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpServletResponse.setHeader("Access-Control-Max-Age", "3600");

if (isOption(httpServletRequest.getMethod())) {
httpServletRequest.setAttribute("isPermit", true);
}

filterChain.doFilter(httpServletRequest, httpServletResponse);
}

public boolean secureMatch(HttpServletRequest request, String origin) {
return request.getHeader("referer").contains(origin);
}

public boolean isOption(String method) {
return HttpMethod.OPTIONS.name().equals(method);
}
}
18 changes: 0 additions & 18 deletions src/main/java/com/moabam/global/config/WebConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@

import java.util.List;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.moabam.api.application.auth.mapper.PathMapper;
Expand All @@ -19,22 +17,6 @@
@EnableScheduling
public class WebConfig implements WebMvcConfigurer {

private static final String ALLOWED_METHOD_NAMES = "GET,HEAD,POST,PUT,DELETE,TRACE,OPTIONS,PATCH";
private static final String ALLOW_ORIGIN_PATTERN = "[a-z]+\\.moabam.com";

@Value("${allow}")
private String allowLocalHost;

@Override
public void addCorsMappings(final CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns(ALLOW_ORIGIN_PATTERN, allowLocalHost)
.allowedMethods(ALLOWED_METHOD_NAMES.split(","))
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(handlerMethodArgumentResolver());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package com.moabam.api.presentation;

import static org.mockito.BDDMockito.*;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
import static org.springframework.test.web.client.response.MockRestResponseCreators.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.mockito.BDDMockito.any;
import static org.mockito.BDDMockito.doReturn;
import static org.mockito.BDDMockito.willReturn;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.cookie;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
Expand Down Expand Up @@ -37,6 +43,7 @@
import com.moabam.api.dto.auth.AuthorizationCodeResponse;
import com.moabam.api.dto.auth.AuthorizationTokenInfoResponse;
import com.moabam.api.dto.auth.AuthorizationTokenResponse;
import com.moabam.global.auth.filter.CorsFilter;
import com.moabam.global.common.util.GlobalConstant;
import com.moabam.global.config.OAuthConfig;
import com.moabam.global.error.handler.RestTemplateResponseHandler;
Expand All @@ -58,6 +65,9 @@ class MemberAuthorizeControllerTest {
@SpyBean
AuthorizationService authorizationService;

@SpyBean
CorsFilter corsFilter;

@Autowired
OAuthConfig oAuthConfig;

Expand All @@ -77,6 +87,7 @@ void setUp() {
RestTemplate restTemplate = restTemplateBuilder.build();
ReflectionTestUtils.setField(oAuth2AuthorizationServerRequestService, "restTemplate", restTemplate);
mockRestServiceServer = MockRestServiceServer.createServer(restTemplate);
willReturn(true).given(corsFilter).secureMatch(any(), any());
}

@DisplayName("인가 코드 받기 위한 로그인 페이지 요청")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ void filter_have_any_refresh_token_error() throws ServletException, IOException
eq(null), any(UnauthorizedException.class));
}

@DisplayName("새로운 도큰 발급 성공")
@DisplayName("새로운 토큰 발급 성공")
@Test
void issue_new_token_success() throws ServletException, IOException {
// given
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package com.moabam.support.common;

import static org.mockito.ArgumentMatchers.*;
import static org.mockito.BDDMockito.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.willReturn;

import java.util.Optional;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;

import com.moabam.api.domain.member.Role;
import com.moabam.global.auth.filter.CorsFilter;
import com.moabam.global.auth.handler.PathResolver;

@ExtendWith({FilterProcessExtension.class})
Expand All @@ -18,8 +21,17 @@ public class WithoutFilterSupporter {
@MockBean
private PathResolver pathResolver;

@MockBean
private DefaultHandlerExceptionResolver handlerExceptionResolver;

@SpyBean
private CorsFilter corsFilter;

@BeforeEach
void setUpMock() {
willReturn(true)
.given(corsFilter).secureMatch(any(), any());

willReturn(Optional.of(PathResolver.Path.builder()
.uri("/")
.role(Role.USER)
Expand Down

0 comments on commit 9e35528

Please sign in to comment.