<img>
, <video>
, <script>
, <link>
태그의 경우 기본적으로 cross-origin 정책을 지원하지만 XMLHttpRequest
, Fetch API
스크립트의 경우 same-origin 정책을 따른다. 자바스크립트에서의 요청은 기본적으로 서로 다른 도메인에 대한 요청을 보안상 제한한다. 브라우저는 기본으로 하나의 서버 연결만 허용되도록 설정되어 있기 때문이다.
protocol + Host + Port
console.log(location.origin);
으로 현 로케이션의 출처를 파악할 수 있다.
동일 출처(Same-Origin) 서버에 있는 리소스는 자유로이 가져올수 있지만,
다른 출처(Cross-Origin) 서버에 있는 리소스 사용을 제한하는 보안방식이다.
만일 SOP가 없을 경우 해커가 개인정보를 가로채는 문제 등이 발생할 수 있다.
SOP 정책으로 동일하지 않은 출처의 스크립트가 실행되지 않도록 브라우저에서 사전에 방지할 수 있다. 문제는 우리는 타 출처의 리소스가 필요할 때가 있다는 것, 그리하여 웹 브라우저에 CORS라는 표준이 마련되었다.
[ 출처를 비교하는 로직은 서버에 구현된 스펙이 아닌 브라우저에 구현된 스펙 ]
서버는 리소스 요청에 대해 정상 응답을 하지만 브라우저가 서버의 응답을 분석하여 동일 출처가 아닐 경우 받을 수 없도록 차단하기 때문에 에러를 보여준다.
(브라우저가 정책으로 차단을 한다는 말은, 브라우저를 통하지 않고 서버 간에 통신을 할때는 정책이 적용되지 않는다는 말과 같다.
즉, 클라이언트 단 코드에서 API 요청을 하는게 아니라, 서버 단 코드에서 다른 출처의 서버로 API 요청을 하면 CORS 에러로부터 자유로워 진다.
이를 이용한 것이 프록시 서버이다.)
추가 HTTP 헤더를 사용하여 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 리소스에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제이다. SOP 정책을 위반하더라도 CORS 정책에 따르면 다른 출처의 리소스라도 허용한다.
- Preflight를 보내면 실질적으로 두번 요청이 보내진다. (사전 요청, 실제 요청)
- OPTIONS 메서드를 통해 다른 도메인의 리소스에 요청 가능한지 확인한다.
- 요청 가능하다면 실제 요청을 보낸다.
** cross-origin 요청은 유저 데이터에 영향을 줄 수 있기 때문에 사전 요청을 진행하는 것 ! **
CORS에서 사전 요청은 OPTIONS 메서드를 통해 전송되므로 요청을 보낼 수 있는 경우라면 서버가 응답한다.
즉, 사전 요청은 본격적인 교차 출처 HTTP 요청 전에 서버 측에서 그 요청의 메서드와 헤더에 대해 인식하고 있는지를 체크하는 것이다.
* Preflight Request
* Preflight Response
사전 요청을 사용할 경우 실제 요청에 걸리는 시간이 늘어나게 되어 어플리케이션 성능에 영향을 미친다는 단점이 있다.
특히 수행하는 API 호출 수가 많으면 많을 수록 사전 요청으로 인해 서버 요청을 배로 보내게 되니 비용 적인 측면에서 좋지 않다.
따라서 브라우저 캐시(Cache) Visit Website 를 이용해 Access-Control-Max-Age 헤더에 캐시될 시간을 명시해 주면, 이 Preflight 요청을 캐싱 시켜 최적화를 시켜줄 수 있다.
Access-Control-Allow-Credentials: true
헤더가 없는 응답을 거부하며 호출된 웹 컨텐츠에 응답을 제공하지 않는다.* 클라이언트측
* 서버측
Access-Control-Allow-Credentails : true
다른 출처끼리 쿠키 통신할 때 클라이언트에서 withCredentials
옵션 활성화해야하는데
Access-Control-Allow-Origin
헤더에 와일드 카드(*)를 사용할 수 없다.
→ 이 때 라우터에 들어온 요청 데이터에 request 객체의 origin 헤더값을 가져와
그대로 Access-Control-Allow-Origin에 넣는 방식 금지한다.
app.get('/users', (req, res) => {
res.header("Access-Control-Allow-Origin", req.headers.origin);
// ...
}
)
공격자는 샌드박스 처리된 iframe을 이용해 Origin 헤더에 NULL을 지정해 요청할 수 있으므로 NULL 출처를 리소스 접근 허용 목록에 포함시키지 말아야 한다.
MDN - SOP
MDN - CORS
MDN - 사전요청
10분 테코톡 - 나봄의 CORS
개인블로그
개인블로그
기타 참고 자료