CORS-크로스 도메인 이슈에 관하여 ====
그동안 API서버를 짜고 ajax요청을 하면 종종 크로스도메인 에러가 발생했었다. 그럴때마다 매번 어떻게 고쳐서 해결했었던거 같은데 이번에도 나고야 말았다. 그래서 이번엔 확실하게 짚고 넘어가기위해 포스트 하기로 했다.
-
CORS란?
cross-origin resource sharing의 약자이다
최근 웹 브라우저들은 보안상의 이유로 javascript나 ajax로 외부host로 접속하는것을 막기 시작했다고 한다.
그래서 javascript는 Same Origin Policy(동일 출처 정책)라는 정책을 두어 다른 도메인의 서버에 요청하는 것을 보안문제로 간주하고 이를 차단하는데, 즉 Javascript는 자신이 속한 동일 도메인 내에서만 서버 요청을 허용하고 처리해 주겠다는 의미이다.
예를들어 www.goyaaaaaaaa.xyz 도메인에서 호출된 ajax는 www.goyaaaaaaaa.xyz도메인 내에 있는 URL만 호출할 수 있다는 것이다.
그러면 www.goyaaaaaaaa.xyz에 있는 ajax에서는 www.ssoma.xyz의 URL을 ajax 호출할 수 없다는 것이다.
이것을 다른 말로는 Sandbox라고 한다고 한다. 샌드박스는 보호영역 안에서만 프로그램을 동작시키며 외부의 영향을 받지 않도록 하는 모델이라고한다. 이것은 어린이들이 모래박스 안에서 다치지않고 놀수있게 한것에서 유래했다고 한다.
-
CORS문제 해결법
그래서 외부 도메인의 접근을 가능하게 하려면 Response header에 필드를 추가하여 허용 범위를 지정할 수 있다.
헤더필드에 Access-Control-Allow-Origin을 추가해준다.
1) 특정 host접근 허용
Access-Control-Allow-Origin : http://www.goyaaaaaaaa.xyz
2) 모든 접근 허용
Access-Control-Allow-Origin : *
-
spring에서 해결법
처음엔 web.xml파일에 filter를 추가하고 url-pattern으로 특정 url 요청이 들어오면 filter클래스에서 처리해주려 했다.
web.xml
<filter>
<filter-name>cors</filter-name>
<filter-class>com.company.project.util.domain.SimpleCORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cors</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
SimpleCORSFilter.java
@Component
public class SimpleCORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
response.setHeader("Access-Control-Allow-Origin", "*");
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {}
public void destroy() {}
}
근데 이렇게 하니까 잘 안먹히길래 그냥 java config 클래스 파일을 만들어서 했더니 오히려 잘 작동하였다.
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://domain2.com")
.allowedMethods("PUT", "DELETE")
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(false).maxAge(3600);
}
}
무튼 해결은 이런식으로 했지만 아직도 어렵다.
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cors.html