다른 출처의 리소스 요청을 제한하는 2가지 정책: SOP & CORS

CORS 에러

CORS 정책을 지키지 않고 보낸 리소스 요청에 대한 에러

CORS란

Cross-Origin Resource Sharing
한 출처에서 실행 중인 웹이 다른 출처의 자원에 접근할 수 있는 권한을 부여하도록 브라우저에서 알려주는 체제. 어떤 호스트에서 자신의 콘텐츠를 불러갈 수 있는지 서버에 지정할 수 있는 방법.

예시
https://domain-a.com의 프론트 엔드 JavaScript 코드가 XMLHttpRequest를 사용하여 https://domain-b.com/data.json을 요청하는 경우

보안상의 이유로 브라우저는 스크립트에서 시작한 교차출처 HTTP 요청을 제한한다. (XMLHttpRequest와 FetchAPI는 동일 출처 정책을 따름). 자신의 출처와 동일한 리소스만 불러올 수 있으며 다른 출처의 리소스를 불러오기 위해서는 그 출처에서 올바른 CORS헤더를 포함한 응답을 반환해야 함.

단순 요청(simple requests)

예비요청없이 바로 서버에 본 요청을 보내는 것.

❗️조건
1. GET, HEAD, POST 메서드 중 하나
2. Accept, Accept-Language, Content-Language, Content-Type 헤더만 허용됨
3.Content-Type을 사용할 경우 application/x-www-form-urlencoded, multipart/form-data, text/plain 값들만 허용됨

프리플라이트 요청(preflight requests)

가장 많이 마주치는 방식. 예비 요청 + 본 요청으로 나눠서 서버에 전송함.
simple requests와 달리 먼저 OPTIONS 메서드를 통해 다른 도메인의 리소스로 HTTP 요청을 보내 실제 요청을 전송하기에 안전한지 확인함. '응답 헤더에 유효한 Access-Control-Allow-Origin이 있는가'를 판단.

  • 브라우저가 CORS 여부를 판단하는 시점: 예비 요청의 응답을 받은 이후
    => 예비 요청 자체가 실패해도 헤더에 Access-Control-Allow-Origin값이 제대로 들어가있다면 CORS 정책 위반이 아님

인증정보를 포함한 요청(credentialed requests)

인증된 요청을 사용하는 방법. 다른 출처 간 보안을 좀 더 강화하고 싶을 때 사용함.

인증정보를 포함한 요청은 HTTP cookies와 HTTP Authentication 정보를 인식함. 브라우저는 Access-Control-Allow-Credentials: true 헤더가 없는 응답을 거부함. CORS 실행 전 요청에 대한 응답은 Access-Control-Allow-Credentials: true를 지정하여 자격 증명으로 실제 요청을 수행할 수 있음을 나타내야 함.

동일 출처 정책(same-origin policy)

어떤 출처에서 불러온 문서나 스크립트가 다른 출처에서 가져온 리소스와 상호작용하는 것을 제한하는 중요한 보안 방식 => 잠재적으로 해로울 수 있는 문서를 분리하여 공격받을 수 있는 경로를 줄여줌

두 URL의 프로토콜(http or https),포트(:80 or :81),호스트가 모두 같아야 동일한 출처 라고 말함

HTTP URL 분석

http://www.example.com:8080/test?search=coffee

|프로토콜|http://|
|호스트(Host/Hostname)|www.example.com:8080|
|서브도메인(Subdomain)|www.|
|도메인|example.com|
|경로(path)|/test|
|파라미터|search|
|파라미터 값|coffee|

출처 비교 예시

URL: http://store.company.com/dir/page.html

URL결과이유
http://store.company.com/dir2/other.html성공경로만 다름
http://store.company.com/dir/inner/another.html성공경로만 다름
https://store.company.com/secure.html실패프로토콜 다름
http://store.company.com:81/dir/etc.html실패포트 다름(http://는 80이 기본값)
http://news.company.com/dir/other.html실패호스트 다름

CORS 에러 해결하기

1/ 서버에서 해결
브라우저에서 CORS 에러 발견 시 서버에게 Access-Control-Allow-Origin에 유효한 값을 포함해서 보내달라고 요청

Access-Control-Allow-Origin:* (모든 출처 허용)을 세팅하면 당장은 편하겠지만 보안 이슈 생길 수 있음

2/ 백엔드와 소통하기 어려운 상황이라면

  • http-proxy-middleware 사용하기
    - 배포 전 로컬환경에서 사용 가능
    • npm install --save-dev http-proxy-middleware
    • src 밑에 setUpProxy.js 파일 생성
//setUpProxy.js

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app){
  app.use(
      createProxyMiddleware('/api', {
          target: 'https://localhost:5000',
          changeOrigin: true
      })
  )
};

참고
MDN: CORS(교차 출처 리소스 공유)
MDN: same-origin policy(동일 출처 정책)

profile
oneThing

0개의 댓글