교차 출처의 자원 공유 = 출처가 다른 자원에 대한 공유
ex) 다음과 같은 주소가 있다고 했을 때, 각각의 아래와 같이 구분된다.
https://
github.com
/nine57/learn_algorithm/search
?q=code
https://
github.com
:8080
/nine57/learn_algorithm/search
?q=code
#foo
여기서 출처에 대한 판단 요소는 Protocol, Host, Port의 세가지로,
각각에 대한 의미를 비교하는 것이 아니라 String자체를 비교하게 된다.
Web이라는 공개된 환경의 특성상 익명의, 부정한 의도가 담긴 공격에 취약할 수 밖에 없다.
이런 위험성 때문에 같은 출처일 경우에만 리소스를 받을 수 있도록 설정해둔 것이 SOP이다.
브라우져에서 http 통신을 할때는 SOP 정책하에 하게된다.
즉, 원칙적으로는 출처가 다른 외부의 리소스들을 사용할 수 없다는 얘기인데, 그렇게 되면 Web의 장점을 사용하기 힘들어진다.
따라서 제한적인 상황에서 SOP를 통과할 수 있게 하는 예외 조건이 있다.
Origin(@request) == Access-Control-Allow-Origin(@response)
위의 두개의 헤더가 같다면 같은 출처라고 인식한다.
OPTIONS라는 메소드를 사용해서 예비 요청을 먼저 보내, 서버에게 요청을 보낼 수 있는지를 확인하고 요청에 대한 허가가 떨어지면 본 요청을 보내게 된다.
PUT이나, DELETE같은 요청을 보낼 경우 서버 쪽에 변경이 발생하게 되는데, SOP는 브라우져 사이드에서 확인을 하는 정책이다. (서버나 클라이언트 사이드의 정책이 아니다!)
만약, SOP에 위배되는 상황인데 위와 같은 요청을 보낸다면, 변경하면 안되는 상황임에도 서버는 그에 대한 구별없이 요청을 수행하고 완료되었다고 200OK를 보낸다.
이에 대한 안전 절차로서 예비 요청을 보내서 요청을 보내도 되는지에 대한 확인을 하는절차이다.
예비 요청없이 바로 본요청을 보낸다.
본 요청에서 SOP여부를 같이 판단하고 요청을 처리하게 되고, 따라서 사용하는데 조금 더 제약이 있다.
위의 제약 사항을 볼 때, REST API에서 jwt 담아서 보내는 요청은 수행할 수 없을 을 알 수 있다.(Token을 담는 Authorization 헤더가 없을 뿐만 아니라, Content-type에 Json이 없다.)
REST 기반의 API에서는 잘 사용하지 않는 방법.
쿠키에 인증 정보를 담아 서버 쪽에서 인증 정보를 검증하고 응답하게 하는 방법.
인증 정보 유무에 따라 다음과 같이 옵션을 지정해서 요청을 보낸다.
보안상 더 안전한 방식을 취하고자 함
옵션 값 | 설명 |
---|---|
same-origin(기본값) | 같은 출처 같 요청에만 인증 정보를 담는다. |
Include | 모든 요청에 인증정보를 담는다. |
Omit | 모든 요청에 인증정보를 담지 않는다. |
이 방법에도 일부 제약사항이 있다.
Server side 에서는
응답헤더에 올바른 Access-Control-Allow-Origin이 내려올 수 있도록 세팅이 필요하다.
Client side 에서는
Webpack Dev Server로 리버스 프록싱하여 우회가 가능
But, 로컬 환경에서만 가능하므로 결론적으로는 서버사이드에서 해결하는 것이 맞다.
Django 에서 사용하는 django-cors-headers 라이브러리가 이를 해결해주는 것!
Reference : [10분 테코톡] 🤠럿고의 CORS