bkdragon's log

CORS 요리 본문

concept

CORS 요리

bkdragon 2023. 7. 29. 15:48

CORS를 정복해보자.

 

SOP

동일 출처 정책 Same Origin Policy

동일한 출처에서만 리소스를 공유할 있게 하는 정책이다. 동일한 출처의 기준은 Protocol, Host, Port가 같을 때이다. 출처에 대한 비교와 차단은 브라우저의 기능이다.

 

 

CORS

교차 출처 리소스 공유 Cross-Origin Resource Sharing

다른 출처의 리소스 공유에 대한 허용/비허용 정책이다. 허용하는 간략한 과정은 다음과 같다.

 

  1. 클라이언트에서 요청을 보낼 때 헤더에 Origin을 보낸다.
  2. 요청을 받은 서버는 응답 헤더에 Access-Control-Allow-Origin을 담아 클라이언트로 보낸다.
  3. 클라이언트에서 Origin과 서버가 보내준 ACAO를 비교하고 유효할 경우에만 리소스를 받아온다.

깊게 들어가면 ACAO 말고도 다른 요소들이 있다.

 

 

Access-Control-Allow-Origin 접근 가능한 url 설정
Access-Control-Allow-Credentials 접근 가능한 쿠키 설정
Access-Control-Allow-Headers 접근 가능한 헤더 설정
Access-Control-Allow-Methods 접근 가능한 http method 설정

이것들을 서버로부터 받아 요청 헤더와 비교를 하게 된다. 비교 과정은 예비 요청의 과정 중에 일어난다.

 

 

Preflight Request (예비 요청)

브라우저는 본 요청을 보내기 전에 예비 요청을 보내 서버와 통신 상태를 확인한다.

이때 메서드는 OPTIONS(임시)가 사용된다.

 

예비 요청 상황을 풀어서 나열하면 다음과 같다.

 

  1. 클라이언트에서 서버에 리소스를 GET 요청한다.
  2. 브라우저에서 서버로 HTTP OPTIONS 메서드로 예비 요청을 보낸다.
    1. Origin에 자신의 출처 (현재 도메인)
    2. Access-Control-Request-Method 에 실제 요청에 사용할 메서드를 설정 (GET)
    3. Access-Control-Request-Headers 에 실제 요청에 사용할 헤더들을 설정
  3. 예비 요청에 대한 응답으로 서버에서 어떤 것을 허용하고 금하는지 정보를 담아 브라우저에 보내준다.
    1. Access-Control-Allow-Origin 헤더에 허용되는 Origin들의 목록을 설정
    2. Access-Control-Allow-Methods 헤더에 허용되는 메소드들의 목록을 설정
    3. Access-Control-Allow-Headers 헤더에 허용되는 헤더들의 목록을 설정
    4. Access-Control-Max-Age 헤더에 해당 예비 요청이 브라우저에 캐시 될 수 있는 시간을 초 단위로 설정
  4. 브라우저에서 보낸 요청과 서버가 보내준 정책을 비교하여 안전하면 본요청을 보낸다.
  5. 본 요청을 보내고 응답을 받아 데이터를 얻어온다.

 

단순 요청 (Simple Request)

특정 조건에만 예비 요청을 생략하고 바로 서버에 본 요청을 보낸다.

조건은 다음과 같다.

 

  1. HTTP 메서드가 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 중 하나여야 한다.

 

인증된 요청 (Credentialed Request)

인증된 요청은 ession id가 저장된 cookie나 access token을 동반한 요청이다. 인증된 요청도 단순 요청처럼 예비 요청이 발생하지 않는다.

 

credentials : include 설정해야지만 요청에 인증과 관련된 정보를 담아서 보낸다.

fetch("<https://example.com/user>", {
	method: "POST",
	credentials: "include", 
    body: JSON.stringify({
        userId,
    }),
})

서버에서도 별도의 설정이 필요하다.

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

분명한 url이나 값이 설정되어야 한다는 뜻이다.

 

 

위 이미지는 어떤 요청일까?

메서드가 OPTIONS 임으로 예비 요청이다. 응답 헤더에 ACAO와 같은 정보가 전혀 없기 때문에 브라우저에서 CORS 에러를 보여준 상황이다.

 

이제 CORS 를 나쁜녀석 취급하면 안된다. CORS는 SOP 정책을 위반하여 다른 도메인의 리소스를 얻기 위한 해결책이니 말이다.

'concept' 카테고리의 다른 글

Async Custom Hook Testing  (0) 2023.08.02
[TEST] Redux 테스트  (0) 2023.07.29
Promise 병렬로 처리하기  (1) 2023.07.29
[Redux] Redux Toolkit  (0) 2023.07.27
[Cookie] 내가 만든 Cookie  (0) 2023.07.26