CORS
#
CORSCross Origin Resource Sharing 정책
#
URLProtocol
https://Host
www.evan-moon.comPath
/usersQuery String
?sort=asc&page=1Fragment
#fooPort
의 생략 → 기본 포트 번호- HTTP 80
- HTTPS 443
#
출처Protocol, Host, Port
서버위치를 찾기 위한 가장 기본적인 요소
출처를 비교
하는 로직은 서버가 아니라 브라우저
에 구현되어 있다.
- 브라우저를 통하지 않은 서버 간 통신은 SOP 가 적용되지 않는다.
- 출처 비교 시 포트 번호를 완전 무시하는 브라우저는 Internet Explorer 밖에 없다.
#
SOP : Same Origin Policy같은 출처에서만 리소스를 공유할 수 있다
- CORS 정책을 지킨 리소스 요청은 출처가 다르더라도 허용한다.
#
예외 조항스크립트, 렌더될 이미지, 스타일 시트, script, img, style 태그
요청 자체는 성공한다
Sec-Fetch-Mode: no-cors
- 헤더의 요청 필드를 설정
- 브라우저가 no-cors 인 경우 다른 출처여도 CORS 정책을 검사하지 않는다.
- 응답을 자바스크립트에게 알려주지 않아 응답 내용을 알 수 없다.
#
CORS 배경출처가 다른 두개의 어플리케이션이 마음대로 소통할 수 있는 것은 위험하다.
웹에서 돌아가는 클라이언트 어플리케이션은 사용자의 공격에 취약하다.
- CSRF (Cross-Site Request Forgery)
- XSS (Cross0Site Scripting)
- 브라우저 개발자도구에서 각종 정보들을 아무런 제제없이 열 수 있다.
- DOM 확인
- 서버 통신 내역
- 리소스 출처
- 자바스크립트 코드 난독화는 암호화가 아니다.
- 난독화가 안되어 있어 소스코드가 그대로 노출되는 사이트들도 많다.
#
CORS 와 브라우저출처는 브라우저가 판별한다. 따라서
CORS를 위반했을 때
- 서버는 정상적으로 응답
- 응답의 파기 여부는 브라우저가 결정
#
CORS 의 기본 동작웹 클라이언트가 다른 출처의 리소스를 요청할 때 기본적인 동작
- 사용자의 첫 요청
- HTTP 프로토콜을 사용하여 요청을 보낸다
- 브라우저는 요청 헤더에
Origin
필드에 요청을 보내는 출처를 함께 담아 보낸다.Origin: https://evan-moon.github.io
- 서버의 응답
- 응답 헤더
Access-Controll-Allow-Origin
를 보낸다.- 리소스에 접근할 수 있는 허용된 출처
- 응답 헤더
- 응답을 받은 브라우저
- 자신이 보냈던
Origin
과 응답 받은Access-Control-Allow-Origin
을 비교하여 유효한지 결정한다.
- 자신이 보냈던
#
Preflight Request웹 어플리케이션을 개발할 때 일반적으로 마주치는 시나리오
브라우저는 예비요청
(Preflight)과 본 요청
으로 나누어서 서버로 전송한다.
#
Preflight본 요청을 보내기 전, 브라우저가 요청을 보내는 것이 안전한지 확인한다.
- HTTP 의
OPTIONS
메서드가 사용된다.
요청
본 요청에 대한 다른 정보들도 미리 알려준다.
Access-Control-Request-Headers
: Content-TypeAccess-Control-Request-Method
: GET
예비 요청에 대한 응답
- 응답 헤더의
Access-Control-Allow-Origin: https://evanmoon.tistory.com
는 요청 헤더의Origin: https://evan-moon.github.io
와 출처가 다르므로 CORS 정책 위반 에러를 띄운다.
#
Simple Request예비 요청이 없다.
- 특정조건이 만족해야 Simple Request 를 할 수 있다.
- 사용이 드물다
언제할 까? TODO
#
Credentialed Request인증된 요청을 사용하는 방법
- CORS 에서 좀더 보안을 강화하고 싶을 때 사용한다.
#
credential비동기 요청 API XMLHttpRequest
객체, fetchAPI
는 브라우저의 쿠키정보나 인증과 관련된 헤더를 담지 않는다.
이때 credential
은 요청에 인증과 관련된 정보를 담을 수 있게 해준다.
#
credential 옵션의 종류Same Origin
(크롬 Default) 같은 출처간 요청에만 인증 정보를 담을 수 있다.include
모든 요청에 인증정보를 담을 수 있다.omit
모든 요청에 인증정보를 담지 않는다.
Same Origin
include
옵션이라면 Access-Control-Allow-Origin
이외에 조건이 더 까다로워진다.
Same Origin
:Access-Control-Allow-Origin: *
허용include
응답헤더에Access-Control-Allow-Origin: *
미허용Access-Control-Allow-Credentials: true
필수
#
CORS 해결 방법#
1. Access-Control-Allow-Origin 세팅- 서버엔진의 설정 nginx, apache
- 소스코드 내에 응답 미들웨어 세팅
- CORS 미들웨어 라이브러리를 찾아보자
#
2. Webpack DevServer 로 리버스 프록싱프론트엔드 개발환경에서 CORS 를 많이 마주칠 것이다.
벡엔드의 Access-Control-Allow-Origin: http://localhost:3000
같이 범용적인 출처를 넣어주는 경우는 드물다.
그래서 프론트엔드의 webpack-dev-server
의 라이브러리의 프록시 기능은 CORS 정책을 우회하게 해준다.
localhost:8000/api
처럼, path 가/api
로 시작되는 요청을 웹팩이https://api.evan.com
으로 요청을 프록싱 해준다.- 브라우저는 여전히
localhost:8000/api
로 알고있다.