CORS A to Z

바퀴달린 개발자·2022년 6월 2일
0

SOP (Same Origin Policy)

: 다른 출처의 리소스를 사용하는 것에 제한하는 보안 방식

출처(origin)이란?

- 도메인 : naver.com
- origin : https://www.naver.com:PORT

origin 이란 프로토콜, 도메인, 포트 번호의 조합이다.
same origin은 프로토콜, 도메인, 포트가 모두 같아야 같은 origin이라고 한다.

Q.
http:localshot와 동일한 출처는?

  1. https://localhost
  2. http://localhost:80
  3. http://127.0.0.1
  4. http://localhost/api/cors

A) 2, 4번
해설)
2번은 http의 기본 포트가 80포트이다.
3번이 아닌 이유는 브라우저 입장에서는 string value로 확인을 해서 다른 출처라고 판단한다.

SOP란?

예시)
1. 사용자가 페이스북 서비스에 로그인한다. (페이스북에서 인증 토큰을 받아온다.)
2. 해커가 사용자에게 링크를 메일을 통해 보낸다.
2-1. 해당 링크에는 페이스북에 '나는 바보다'라는 포스트를 등록하는 스크립트가 작성되어 있다.
3. 사용자가 링크를 클릭하면 해당 인증 토큰을 가지고 포스트를 게시하라고 명령을 한다.
4. 페이스북에서 여기에 Origin을 보면 해커가 보낸 Origin은 다른 출처라고 판단해서 해당 명령을 거부한다.

이렇듯 SOP란 같은 Origin일 때만 요청을 허가하는 것을 말한다.
그리고 웹 브라우저는 SOP에 의해 하나의 웹 페이지에서 다른 웹 페이지의 데이터에 접근하기 위한 스크립트가 있을 때, 두 웹페이지가 같은 Origin일 때만 이를 허가한다.

그렇다면 다른 출처의 리소스가 필요할 때는 어떻게 하는가?? 바로 CORS를 사용한다.

CORS (Cross-Origin Resource Sharing)

  • 다른 출처의 자원을 공유한다.
  • SOP를 완화하는 테크닉 중 하나다.
  • 추가 HTTP 헤더를 사용하여, 한 출처에서 실행중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제이다.

CORS 동작 종류

1. 단순 요청 (Simple Request)

=> 바로 본 요청을 보낸다.

조건

  • HTTP method가 GET, POST, HEAD 중에 하나이어야 한다.
  • Content-Type이 application/x-www.-form-urlencoded, multipart/form-data, text/palin 중 하나여야 한다.
  • 헤더는 Accept, Accept-Language, Conent-Language, Contest-Type만 허용한다.

해당 조건을 만족하면 추가적인 확인 없이 바로 본 요청을 보낸다.

2.프리플라이트 요청 (Preflight Request)

=> 사전 확인 작업
1. options 메서드(request-method)를 통해 다른 도메인의 리소스에 요청이 가능한 지 확인 작업
2. 요청이 가능하다면 실제 요청(Actual Request)을 보낸다.

preflight request

ㄴ origin : 요청 출처
ㄴ Access-Control-Request-Method: 실제 요청의 메서드
ㄴ Access-Control-Request-Headers : 실제 요청의 추가 헤더를 뭐뭐 보낼 수 있는지

preflight response

ㄴ Access-Control-Allow-Origin: 서버 측 허가 출처
ㄴ Access-Control-Allow-Methods: 서버 측 허가 메서드
ㄴ Access-Control-Allow-Headers: 서버 측 허가 헤더
ㄴ Access-Control-Max-Age: Preflight 응답 캐시 기간

preflight respose의 특징 : 응답 코드는 200대여야한다. 응답 바디는 비워져 있는 것이 좋다.

simple request가 있는데 왜 필요할까?

  • CORS 설정이 안되어 있는 서버를 위해서
  • 서버에서는 CORS 설정이 안되어 있기 때문에 처리를 다함. 하지만 allow-origin이 없기 때문에 브라우저에서는 에러를 보낸다.
  • 그래서 preflight request가 필요하다.

3.인증 정보 포함 요청 (Credentialed Reqeust)

  • 인증 관련 헤더를 포함할 때 사용하는 요청
  • 서버에서도 설정을 해줘야 클라이언트측에서 보내는 것을 받을 수 있다.

클라이언트 측
credentials: include

서버측
Access-Control-Allow-Credentials: true
(Access-Control-Allow-Origin: *은 안된다. 정확한 origin을 줘야한다.)

CORS 설정

Access-Control-Allow-Origin 세팅하기

  • Nginx, apache 서버 설정에 추가
  • spring, django 등 백엔드 프레임워크에서 제공해주는 라이브러리로 설정 (권장)

질문..
preflight로 보낼지 simple로 보낼지는 누가 결정하는거임

0개의 댓글