CORS란?
test2.com:8080사이트와 test.com:18080 사이트는 도메인과 포트가 다르다. 따라서 test.com:18080에서 test2.com:8080사이트로 요청을 보내게 되면 아래와 같은 에러를 만날 수 있다.
Access to XMLHttpRequest at 'http://domain1:8080/xxxxx' from origin 'http://test.com:18080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
http://localhost:8080/test/1 를 기준으로 비교해보면
URL | 출처 | 비고 |
http://localhost:8080/test/2 | 동일출처 | protocol, host, port 동일 |
http://localhost:8080/sample | 동일출처 | protocol, host, port 동일 |
https://localhost:8080/test | 다른출처 | protocol 다름 |
http://localhost:18080/test/1 | 다른출처 | port 다름 |
http://test.com:8080/test/1 | 다른출처 | host 다름 |
protocol, host, port가 모두 동일하면 동일출처이고, 하나라도 같지 않으면 다른출처이다.
동일출처는 SOP(Same-Origin Policy)로 웹브라우저 상에서 보안상 이슈가 없지만 다른출처의 경우 보안상 이슈로 인해 웹브라우저상에서 에러메시지가 출력되고, 이를 해결하기 위해서는 CORS를 설정해주어야 한다.
CORS는 Cross-Origin Resource Sharing의 줄임말로 직역하면 '교차 출처 리소스 공유'라고 해석할 수 있다. 여기서 '교차 출처'라고 하는 것은 '다른 출처'를 의미한다. 간단히 말하자면 CORS는 다른 출처에 액세스 할 수 있게하는 보안 메커니즘이다.
test.com:18080 사이트에서 test2.com:8080 사이트에 엑세스할 수 있도록 하기 위해선 아래 방법 중 하나를 이용하여 설정해야 한다.
방법 1 - @CrossOrigin
@CrossOrigin(origins = "http://test.com")
요청을 보내는 client 사이트의 도메인을 설정해주면 되고, Controller나 Controller의 메소드에 추가하여 특정 API마다 설정 가능하다.
Global하게 설정하려면 방법2, 방법3을 이용하면 된다.
방법 2 - <mvc:cors>
servlet-context.xml에 아래 코드를 추가해주었다.
<mvc:cors>
<mvc:mapping path="/**" allowed-origins="*" allowed-methods="POST,GET" allow-credentials="true"/>
</mvc:cors>
- 특정 도메인만 허용하고자 한다면 allowed-origins="http://test.com"를 설정해주면 된다.
- 여러 특정 도메인을 허용하고자 한다면 allowed-origins="http://test.com, http://sample.com"를 설정해주면 된다. (콤마로 구분)
방법 3 - Filter
<filter>
<filter-name>corsFilter</filter-name>
<filter-class>com.dreamsecurity.framework.filter.CorsFilter</filter-class>
<init-param>
<param-name>allow-origin</param-name>
<param-value>http://sample.com:28080, http://test.com:18080</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>corsFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
public class CorsFilter implements Filter{
Logger logger = LogManager.getLogger(CorsFilter.class.getName());
private String allowOrigin;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.allowOrigin = (String)filterConfig.getInitParameter("allow-origin");
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if(allowOrigin != null) {
String[] allowOrigins = allowOrigin.split(",");
boolean isAllowOrigin = false;
for(String origin : allowOrigins) {
if(origin.equals(request.getHeader("Origin"))) {
isAllowOrigin = true;
break;
}
}
if(isAllowOrigin) {
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true"); //쿠키 요청을 허용
response.setHeader("Access-Control-Allow-Methods","POST, GET"); //허용할 HTTP 메서드
response.setHeader("Access-Control-Allow-Headers", "*"); //요청을 허용할 헤더
chain.doFilter(req, res);
}
}
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
}
그리고 인터셉터로 처리하는 방법도 있다고 한다.
Spring Boot에선 주로 WebMvcConfigurer 에서 cors 설정을 하던데 이는 추후 포스팅하는걸로..!
'개발 > Web' 카테고리의 다른 글
[Spring] 빈(bean)을 등록하는 방법 (0) | 2022.07.01 |
---|---|
[Web] 동기 방식과 비동기 방식의 차이점 (3) | 2022.05.04 |
[Web] Received fatal alert: handshake_failure 에러 (0) | 2022.03.08 |
[Web] Restful API란? (1) | 2022.02.21 |
[Spring] Bean 등록 방법 : @Bean vs @Component 차이 (0) | 2022.02.03 |
댓글