본문 바로가기
개발/Web

[Spring Framework] CORS 적용하기 - @CrossOrigin, <mvc:cors>, Filter

by zuzuu 2022. 3. 11.
반응형

 

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 설정을 하던데 이는 추후 포스팅하는걸로..!

 

 

728x90
반응형

댓글