본문 바로가기
Spring

CORS(Cross Origin Resource Sharing)

by 루에 2022. 7. 9.
반응형

요약

직역하자면 교차 출처 자원 공유. 사용되는 의미는, 출처가 다른 자원에 대한 공유를 허용하는 [규칙]이다. CORS 규칙을 지키지 않은 요청에 대해서 막겠다는 의미.

출처라고 하면 스킴과 호스트, 포트를 의미한다. 예를 들면 https://naver.com:8080 이다. 이 경우 https 스킴에 naver.com 호스트이며 8080 포트로 들어온 요청만 받는다는 SOP(Same Origin Policy) 규칙에서 예외 조항을 설정한다면 그게 CORS 규칙이 될 것이다.

 

출처를 비교하는 스펙은 기본적으로 브라우저 스펙이다. 요청이 들어오면 서버로 요청하여 응답을 받고 출처를 비교해 SOP를 어겼다면 리젝한다. 브라우저를 통하지 않은 요청을 당연히 비교하지 않는다. 

 

CORS 동작 방식

http요청을 예비요청(preflight)와 본요청으로 나누어진다.

http요청 시 최초 origin 이라는 항목을 헤더에 담아 예비 요청을 한다.

예비 요청을 하면 서버는 허용되는 규칙에 대해 응답하며 출처에 대한 값은 Access-Control-Allow-Origin 에 담겨있다.

예비 요청에 사용되는 함수는 OPTIONS로 origin 뿐만 아니라 여러 정보를 보내고 적절한 응답을 받게 되며 아래같은 정보를 담고 받는다.

 

요청

OPTIONS https://evanmoon.tistory.com/rss

Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,ko;q=0.8,ja;q=0.7,la;q=0.6
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: GET
Connection: keep-alive
Host: evanmoon.tistory.com
Origin: https://evan-moon.github.io
Referer: https://evan-moon.github.io/2020/05/21/about-cors/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site

 

응답

OPTIONS https://evanmoon.tistory.com/rss 200 OK

Access-Control-Allow-Origin: https://evanmoon.tistory.com
Content-Encoding: gzip
Content-Length: 699
Content-Type: text/xml; charset=utf-8
Date: Sun, 24 May 2020 11:52:33 GMT
P3P: CP='ALL DSP COR MON LAW OUR LEG DEL'
Server: Apache
Vary: Accept-Encoding
X-UA-Compatible: IE=Edge

 

Simple Request

예비요청 없이 본요청만 보내고 CORS를 검사할 수 있으며 Simple Request라고 한다. 하지만 아무 때나 가능한 것은 아니며, 아래 조건을 충족해야한다.

  1. 요청의 메소드는 GET, HEAD, POST 중 하나여야 한다.
  2. Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width를 제외한 헤더를 사용하면 안된다.
  3. 만약 Content-Type를 사용하는 경우에는 application/x-www-form-urlencoded, multipart/form-data, text/plain만 허용된다.

 

Spring에서의 CORS 세팅 예제

@Bean
	public CorsConfigurationSource corsConfigurationSource() {
		CorsConfiguration corsConfiguration = new CorsConfiguration();
		corsConfiguration.setAllowedHeaders(Collections.singletonList("*")); // 허용할 Header
		corsConfiguration.setAllowedOriginPatterns(Collections.singletonList("*")); // 허용할 URL
		corsConfiguration.setAllowedMethods(
			Arrays.asList("GET", "POST", "PUT", "DELETE")); // 허용할 Http Method
		corsConfiguration.setAllowCredentials(true);

		UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
		source.registerCorsConfiguration("/**", corsConfiguration);
		return source;
	}

 

자세한건 아래 참조

https://evan-moon.github.io/2020/05/21/about-cors/

반응형

댓글