SOP와 CORS

yongtae·2024년 5월 1일

Web

목록 보기
1/3
post-thumbnail

SOP와 CORS를 가장 잘 설명하는 이미지이다.

SOP

SOP(Same Origin Policy) : 동일 출처 정책

먼저 origin이란?


Origin(출처)란 Protocol + Host + Port 을 말한다.

정의

JS엔진 표준스펙의 보안규칙으로, 브라우저가 서버로 요청을 보낼 때

  • 프로토콜 (protocol),
  • 호스트 (host),
  • 포트 번호 (port)

가 일치하는 자원과만 상호작용 하도록 요청 발생을 조절하는 정책이다.

해당 출처비교는 서버의 역할이 아닌 브라우저의 역할로, 서버로 보내기전에 브라우저에서 체크하는 것.
출처가 다를 경우 CORS 정책을 따른다.

CORS

CORS(Cross-Origin Resource Sharing) : 교차 출처 리소스 공유
다른 출처의 자원을 공유.

정의

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

즉, 앞서 설명 했던 JS의 보안규칙인 SOP를 벗어나게 해주는 정책이 CORS이다.

필요한 이유?

CORS 없이 데이터를 요청할 수 있게 되면, 다른 사이트에서 원래 사이트를 흉내낼 수 있게 된다.

기존 사이트와 완전히 동일하게 동작하도록 하여 사용자가 로그인을 하도록 하고, 로그인했던 세션 또는 토큰을 탈취하여 악의적으로 정보를 꺼내오거나 다른 사용자의 정보를 입력하는 등 해킹을 할 수 있다.

이런 공격을 할 수 없도록 브라우저에서 보호하고, 필요한 경우에만 서버와 협의하여 요청을 하기 위해 필요한 것이 CORS이다.

위반 절차

웹을 사용하면서 CORS 오류에 허덕였던 적이 많았다...
이에 대해서 자세히 알아보자.

  1. 일단, 웹(브라우저)에서 서버로 요청할 때 주로 발생한다.
  2. 브라우저에서 요청을 보낼 때 헤더에 현재 origin을 추가로 담아 Request를 보낸다.
  3. 서버에서는 Request을 받고, 응답 헤더 안에 Access-Control-Allow-Origin을 포함하여 Response를 보낸다.
  4. 브라우저는 Request의 origin,
    Response의 Access-Control-Allow-Origin을 비교한다.
  5. 만약 응답 받은 헤더의 Access-Control-Allow-Origin안에 현재 origin이 포함되어 있지 않다면, 해당 응답에서 CORS 위반 오류를 내보낸다.

즉, 정보를 요청하는 곳의 출처와 응답을 보내는 곳의 출처가 다르다면 CORS오류가 발생한다.
배포나 서비스단계가 아닌, 일반적인 개발 단계에서 구현할 때는 웹 서버와 웹 클라이언트의 출처가 다른 경우가 일반적이기 때문에 (나는 그랬다) 발생했던 것이었다.

CORS 요청 방식

Simple Request (단순 요청)

별도의 예비 요청없이 바로 본요청을 보내는 경우를 말한다.

순서

  1. 서버로 요청
  2. 서버의 응답이 왔을 때, 브라우저가 요청한 Origin
    Access-Control-Request-Header의 값을 비교하여 유효한 요청이면 리소스 응답,
    유효하지 않은 요청이면 브라우저에서 막고 에러 발생시킨다.

Preflight Request (예비 요청)

실제 요청 전에 인증 헤더를 전송하여 서버의 허용 여부를 미리 체크하는 요청을 말한다.
OPTIONS를 활용하여 미리 요청을 먼저 보낸 뒤, Main Request를 보내는 상황이다.

순서

  1. HTTP Method의 OPTIONS 를 사용, Access-Control-Request-* 형태의 헤더를 전송한다.

    HTTP Header의미
    Access-Control-Request-Method실제 요청에서는 어떤 메소드를 사용할 것인지 서버에 알리기 위해 사용
    Access-Control-Request-Headers실제 요청에서는 어떤 헤더를 사용할 것인지 서버에 알리기 위해 사용

    추가적으로, Access-Control-Allow-Origin에 현재 요청하는 곳의 origin을 담아 내용없이 헤더만 전송한다.

  2. 서버 판단하에 유효한 요청일 경우, 브라우저는 보내려던 실제 요청으로 다시 보내면 된다.

  3. 유효하지 않다면 요청 중단, 에러를 발생시킨다.

Credentialed Request (보안 요청)

HTTP 통신에서 해당 옵션이 참이어야 쿠키를 요청/응답 받을 수 있다.
브라우저, 서버 둘 다 모두 credential에 관련된 값이 true여야 한다.

  • 클라이언트(브라우저)측에서는 주로 헤더 객체 인자로 withCredentials: true (axios 예시)
  • 서버 측에서는 헤더의 옵션을
    Access-Control-Allow-Credentials: true
    Access-Control-Allow-Credentials: include
    로 설정해 주어야한다. (두 옵션 모두 동일한 의미이다.)

한 쪽이라도 해당 옵션이 없다면, 클라이언트는 요청에 쿠키를 담아 보낼 수 없고, 서버는 제대로 응답하지 않고 무시할 것이다.
JWT등의 쿠키를 활용한 HTTP 통신 구현에서 해당 옵션이 필수적이다.

CORS 헤더

요청 헤더

  • Access-Control-Allow-Methods
    • preflight일 때 사용, 본 요청에서 어떤 method를 사용할 것인지
  • Access-Control-Allow-Headers
    • preflight일 때 사용, 본 요청에서 어떤 헤더를 사용할 것인지

응답 헤더

  • Access-Control-Allow-Origin
    • 브라우저가 해당 origin의 자원에 접근할 수 있도록 허용한다.
    • * (와일드카드)로 설정하면 credentials가 없는 요청에 한해 모든 origin에서 접근이 가능하다.
      즉, Access-Control-Allow-Credentials을 true로 설정하면 와일드카드 활용은 불가능하다.
  • Access-Control-Allow-Credentials
    • 이 값이 true일 때, HTTP 통신에서 쿠키를 활용할 수 있다.
    • true일 때만, 브라우저가 프런트엔드 JS에 응답을 노출 시킨다.

출처

profile
성장하는 프런트엔드 개발자

0개의 댓글