Backend/Spring+Boot

크로스 도메인 이슈

findmypiece 2021. 4. 29. 12:26
728x90

Javascript 는 동일 출처 정책(Same Origin Policy) 라는 정책을 두어 다른 도메인의 서버에 요청하는 것을 보안 문제로 간주하고 이를 차단한다. 요즘은 마이크로서비스 구조에서는 javascript 단에서도 타 서비스의 api를 호출해야 하는 경우가 많기 때문에 이에 대한 처리가 반드시 필요하며 이를 CORS(Cross-Origin Resource Sharing) 라 한다. 

 

서버가 Spring 환경이라면 아래와 같이 Filter를 등록하는 것만으로 CORS 처리를 할 수 있다. 간단하게 원리를 설명하면 실제요청전 예비요청(Preflight request)을 통해 허용가능한 도메인, 메소드 등을 응답하고 이를 통해 통신을 하는 방식이다.

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CORSFilter extends OncePerRequestFilter {

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
		response.setHeader("Access-Control-Allow-Origin", "*");
		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, Key, Authorization");

		if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
			response.setStatus(HttpServletResponse.SC_OK);
		} else {
			filterChain.doFilter(request, response);
		}
	}
}

 

ajax를 사용한다고 하면 아래와 같이 도메인을 포함해서 api를 호출하면 된다.

$.ajax({
  url: 'http://mypiece.test.com/test',
  data: {
    param_1 : '111'
    ,param_2 : '222'
  },
  type: 'GET',
  dataType : 'json',
  success: function(data) {
    console.log(data);
  },
  error: function(e) {
    console.log(e);
  }
});

 

일반적인 상황이라면 위와 같이 사용해도 잘 동작하지만 서버측에 세션 같은 별도의 인증이 필요하다면 추가 설정이 필요하다. 우선 서버쪽 Filter는 아래와 같이 변경되어야 한다.

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CORSFilter extends OncePerRequestFilter {

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
		response.setHeader("Access-Control-Allow-Origin", request.getHeader("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, Key, Authorization");

		if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
			response.setStatus(HttpServletResponse.SC_OK);
		} else {
			filterChain.doFilter(request, response);
		}
	}
}

Access-Control-Allow-Credentials true 설정이 추가되었는데 Request에 쿠키, authorization 헤더들 또는 TLS 클라이언트 인증서 등을 담아 보내는 것을 허용한다는 설정이다. 그런데 이 경우 Access-Control-Allow-Origin * 같은 정규식을 사용할 수 없기 때문에 위와 같이 Origin값을 직접 명시적으로 지정하도록 한다. Request의 Origin 헤더를 동적으로 받아서 설정하기 때문에 *과 동일한 설정이다.

 

다음으로 ajax 구문도 아래와 같이 변경되어야 한다.

$.ajax({
  url: 'http://mypiece.test.com/test',
  data: {
    param_1 : '111'
    ,param_2 : '222'
  },
  type: 'GET',
  dataType : 'json',
  xhrFields: {
    withCredentials: true
  },
  success: function(data) {
    console.log(data);
  },
  error: function(e) {
    console.log(e);
  }
});

xhrFields 에 withCredentials true 가 추가되었는데 이를 통해 XMLHttpRequest 를 생성할 때 쿠키, authorization 헤더들 또는 TLS 클라이언트 인증서 등을 포함하게 된다. 

728x90

'Backend > Spring+Boot' 카테고리의 다른 글

spring cloud config 비활성화  (0) 2021.05.04
Request 정보 Logging 하기  (0) 2021.05.04
@RestController  (0) 2021.04.27
@ResquestParam, @RequestBody 와 Get, Post  (0) 2021.04.26
threadContextInheritable  (0) 2021.04.23