프로젝트 진행 중 아래와 같은 CORS 에러가 발생하여 이에 대한 해결 방법을 정리했습니다.
Access to XMLHttpRequest at '외부 API URL' from origin '외부 API를 호출한 URL' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
CORS란?
Cross-Origin Resource Sharing의 약자로 도메인이 다른 외부 서버 자원에 접근했을 때, 허용된 방식이 아닌 경우 CORS 에러가 발생합니다.
CORS 를 허용하는 설정 방법이 3가지가 있는 데, 이중 두가지 방법에 대해서 잘 적용되지 않아 filter를 직접 등록하는 방법으로 구현했습니다.
이유는 모르겠는데 아래 방법으로 설정했을 경우 잘 적용되지 않았습니다.
1. WebMvcConfigurer 인터페이스 구현을 통한 addCorsMappings 메소드 추가
2. 컨트롤러에 @CrossOrigin 어노테이션 추가
그래서 Filter 등록 방식으로 구현해보고자 합니다.
테스트하는 스프링 부트 버전, JDK 버전은 다음과 같습니다.
JDK 17
springframework.boot 2.6.7
1. CorsFilter를 컴포넌트로 등록한다
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Order(Ordered.HIGHEST_PRECEDENCE)
@Component
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "*");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, authorization");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
}
response.setHeader("Access-Control-Allow-Origin", "*");
허용하고 싶은 도메인을 지정합니다. "*" 일 경우 모든 도메인에 대한 자원 접근을 허용합니다.
response.setHeader("Access-Control-Allow-Credentials", "true");
true로 설정하면 credentials를 이용한 요청을 처리할 수 있습니다.
response.setHeader("Access-Control-Allow-Methods", "*");
접근가능한 method를 지정합니다 (GET, POST, PATCH, PUT, DELETE)
response.setHeader("Access-Control-Max-Age", "3600");
preflight 요청에 대한 응답을 브라우저에서 얼마만큼 캐싱하고 있을지 설정할 때 사용합니다.
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, authorization");
서버에서 허용하는 header의 key값을 정의합니다.
'IT > Spring' 카테고리의 다른 글
[Retrofit] Retrofit을 이용해서 다양한 방식으로 API 요청을 해보자 (0) | 2022.02.05 |
---|---|
[SpringBoot] resource 값을 자바 소스에서 활용하기 (0) | 2021.07.19 |
[SpringBoot] application.yml 값 암호화 하기 (jasypt) (1) | 2021.07.19 |
[SpringBoot] HATEOAS 적용하기 (0) | 2021.06.17 |
[SpringBoot] H2 데이터베이스 사용하기 (0) | 2021.06.17 |