[CS] CORS (CrossOriginResourceSharing)

hyewon jeong·2023년 4월 7일
0

CS

목록 보기
20/22

1. ⚡️CORS 란?

CrossOriginResourceSharing ( 교차출처 자원공유정책) 는 한 출처에 있는 자원에서 다른 출처에 있는 자원에 접근하도록 하는것으로 교차되는 출처의 자원들의 공유를 의미합니다. 다른 출처의 리소스를 가져오는 상황에서 SOP(Same Origin Policy)는 이 접근을 차단하지만 CORS 설정을 통하여 Access-Control-Allow-Origin 을 서버의 응답헤더에 작성하게 되면 접근 권한을 얻을 수 있습니다.

- 🖥️브라우저가 요청 Origin과 응답헤더의 Access-Control-Allow-Origin의 출처를 비교하여 차단 또는 허용 한다.

1-1. 출처(Origin) 란?

우리가 어떤 사이트를 접속할때 인터넷 주소창에 URL이라는 문자열을 통해 접근하게 된다.

이처럼 URL은 https://domain.com:3000/user?query=name&page=1 과 같이 하나의 문자열 같지만, 사실은 다음과 같이 여러개의 구성 요소로 이루어져 있다.

  • Protocol(Scheme) : http, https
  • Host : 사이트 도메인
  • Port : 포트 번호
  • Path : 사이트 내부 경로
  • Query string : 요청의 key와 value값
  • Fragment : 해시 태크
    몇몇 독자분들 중에 이미 각 URL의 속성들에 대해 다 알고있는 수준이 높은 분들도 있고, 아직은 상세히 잘 모르는 분들도 계실거라 추측한다.

CORS를 이해하는데 있어 저것들을 모두 알아야 되는 것은 아니고, 딱 3가지만 기억하면 된다.

Origin : Protocol + Host + Port
즉, 출처(Origin) 라는 것은 Protolcol 과 Host 그리고 Port 까지 모두 합친 URL을 의미한다고 보면 된다.

1-2CORS 작동 방식 3가지 시나리오

(1) 예비 요청 **(Preflight Request)**

사실 브라우저는 요청을 보낼때 한번에 바로 보내지않고, 먼저 예비 요청을 보내 서버와 잘 통신되는지 확인한 후 본 요청을 보낸다.

즉, 예비 요청의 역할은 본 요청을 보내기 전에 브라우저 스스로 안전한 요청인지 미리 확인하는 것이다.

이때 브라우저가 예비요청을 보내는 것을 Preflight라고 부르며, 이 예비요청의 HTTP 메소드를 GET이나 POST가 아닌 OPTIONS라는 요청이 사용된다는 것이 특징이다.

**⏰ 예비 요청의 문제점과 캐싱**

요청을 보내기 전에 OPTIONS 메서드로 예비 요청을 보내 보안을 강화하는 목적의 취지는 좋다. 그러나 결국은 실제 요청에 걸리는 시간이 늘어나게 되어 어플리케이션 성능에 영향을 미치는 크나큰 단점이 있다.

특히 수행하는 API 호출 수가 많으면 많을 수록 예비 요청으로 인해 서버 요청을 배로 보내게 되니 비용 적인 측면에서 폐가 될 수 있다. 따라서 브라우저 캐시(Cache)Visit Website 를 이용해 Access-Control-Max-Age 헤더에 캐시될 시간을 명시해 주면, 이 Preflight 요청을 캐싱 시켜 최적화를 시켜줄 수 있다.

(2) **단순 요청 (Simple Request)**

다만, 심플한 만큼 특정 조건을 만족하는 경우에만 예비 요청을 생략할 수 있다.

대표적으로 아래 3가지 경우를 만족 할때 만 가능하다.

  1. 요청의 메소드는 GET, HEAD, POST 중 하나여야 한다.
  2. AcceptAccept-LanguageContent-LanguageContent-TypeDPRDownlinkSave-DataViewport-WidthWidth 헤더일 경우 에만 적용된다.
  3. Content-Type 헤더가 application/x-www-form-urlencodedmultipart/form-datatext/plain중 하나여야한다. 아닐 경우 예비 요청으로 동작된다.

이처럼 다소 까다로운 조건들이 많기 때문에, 위 조건을 모두 만족되어 단순 요청이 일어나는 상황은 드물다고 보면 된다.

왜냐하면 대부분 HTTP API 요청은 text/xml 이나 application/json 으로 통신하기 때문에 3번째 Content-Type이 위반되기 때문이다.

따라서 대부분의 API 요청은 그냥 예비 요청(preflight)으로 이루어진다 라고 이해하면 된다.

(3) **인증된 요청 (Credentialed Request)**

인증된 요청은 클라이언트에서 서버에게 자격 인증 정보(Credential)를 실어 요청할때 사용되는 요청이다.

여기서 말하는 자격 인증 정보란 세션 ID가 저장되어있는 쿠키(Cookie) 혹은 Authorization 헤더에 설정하는 토큰 값 등을 일컫는다

**1. 클라이언트에서 인증 정보를 보내도록 설정하기**

// jQuery 라이브러리
$.ajax({
	url: "https://example.com:1234/users/login",
	type: "POST",
	contentType: "application/json; charset=utf-8",
	dataType: "json",		
	xhrFields: { 
    	withCredentials: true // 클라이언트와 서버가 통신할때 쿠키와 같은 인증 정보 값을 공유하겠다는 설정
    },
	success: function (retval, textStatus) {
		console.log( JSON.stringify(retval));
	}
});

**2. 서버에서 인증된 요청에 대한 헤더 설정하기**

  1. 응답 헤더의 Access-Control-Allow-Credentials 항목을 true로 설정해야 한다.
  2. 응답 헤더의 Access-Control-Allow-Origin 의 값에 와일드카드 문자("*")는 사용할 수 없다.
  3. 응답 헤더의 Access-Control-Allow-Methods 의 값에 와일드카드 문자("*")는 사용할 수 없다.
  4. 응답 헤더의 Access-Control-Allow-Headers 의 값에 와일드카드 문자("*")는 사용할 수 없다.

*// 스프링 서버 전역적으로 CORS 설정*

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
			 registry.addMapping("/**")
			.allowedOrigins("http://localhost:8080", "http://localhost:8081")*// 허용할 출처*
			.allowedMethods("GET", "POST")*// 허용할 HTTP method*
			.allowCredentials(true)*// 쿠키 인증 요청 허용*
			.maxAge(3000)*// 원하는 시간만큼 pre-flight 리퀘스트를 캐싱*
			
			}
			}

WebMvcConfigurer

WebMvcConfigurer는 inteface이다.

@EnableWebMvc를 통해 Spring MVC를 위한 커스터마이즈드된 java-based configuration을 정의한다.

addCorsMapping(CorsRegistry registry)

since version : 스프링 4.2

global corss origin request process를 설정한다.

@EnableWebMvc

이 어노테이션을 사용하면 WebMvcConfigurer타입의 빈을 이용해 mvc 설정을 추가로 생성할 수 있다.

참고

Web has been blocked by CORS policy 에러

profile
개발자꿈나무

0개의 댓글