CORS

hatban·2023년 3월 27일
0

cross-origin?

cross-origin 이란 다음 중 하나라도 다른 경우

  1. 프로토콜 : http와 https는 프로토콜이 다르다
  2. 도메인 : domain.com과 other-domain.com은 다르다
  3. 포트번호 : 8080포트와 3000번 포트는 다르다

이런 cross-origin 요청을 하려면 서버의 동의가 필요하다

서버가 동의한다면 브라우저에서는 요청을 허락하고 동의하지않는다면 브라우저에서 거절한다

CORS

  • 이렇게 허락을 구하고 거절하는 메커니즘을 http-header를 통해 할 수 있는데 이것이 CORS다

왜 필요한가?

  • cors없이 모든 곳에서 데이터를 요청하면 다른 사이트에서 원래 사이트를 흉내낼 수있다.
  • 사용자를 속여 로그인 시키게 만들어 세션을 탈취하고 정보를 빼돌리는 등의 공격가능

URL 구조

다른 출처의 출처가 무엇인지 살펴봐야 하는데, 출처가 무엇인지 알기 위해서 먼저 URL의 구조를 살펴보아야 한다. URL 구조는 아래 그림과 같다.

https://beomy.github.io/assets/img/posts/browser/url.png

프로토콜의 HTTP는 80번, HTTPS는 443번 포트를 사용하는데, 80번과 443번 포트는 생략이 가능

출처(Origin)란?

출처(Origin)란 URL 구조에서 살펴본 Protocal, Host, Port를 합친 것을 말한다. 브라우저 개발자 도구의 콘솔 창에 location.origin를 실행하면 출처를 확인할 수 있다.

같은 출처 VS 다른 출처

현재 웹페이지의 주소가 https://beomy.github.io/tech/일 때 같은 출처인지 다른 출처인지 아래 테이블과 같은 결과를 얻을 수 있다

URL결과이유
https://beomy.github.io/about같은 출처Protocal, Host, Port 동일
https://beomy.github.io/about?q=work같은 출처Protocal, Host, Port 동일
https://beomy.github.io/about#work같은 출처Protocal, Host, Port 동일
http://beomy.github.io다른 출처Protocal 다름
https://beomy.github.io:81/about다른 출처Port 다름
https://beomy.heroku.com다른 출처Host 다름

⇒ 출처를 비교하는 로직은 서버단이 아닌 브라우저 단에서 이루어짐!

CORS의 동작

Simple Request(단순요청)

  1. 서버로 요청
  2. 서버 응답이 오면 브라우저가 요청한 Origin 과 응답한 헤더의 Access-Control-Request-Headers의 값을 비교해 유효하면 리소스 응답

💡 Simple request란?

HTTP method 가
- GET
- HEAD
- POST

설정할 수 있는 다음 헤더들만 변경 ⇒ 사용자 인증에 사용되는 Authorization 헤더도 포함 x라 까다롭
- Accept
- Accept-Language
- Content-Language

Content-Type ⇒ 많은 API가 application/json을 사용해 어려운조건이다
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain

preflight 요청일 경우(예비요청)

  • 서버에 예비 요청을 보내 안전한지 판단한 후 본 요청 보내기

  1. Origin헤더에 현재 요청하는 origin과, Access-Control-Request-Method헤더에 요청하는 HTTP method와 Access-Control-Request-Headers요청 시 사용할 헤더를 OPTIONS 메서드로 서버로 요청합니다. 이때 내용물은 없이 헤더만 전송합니다.
  2. 브라우저가 서버에서 응답한 헤더를 보고 유효한 요청인지 확인합니다. 만약 유효하지 않은 요청이라면 요청은 중단되고 에러가 발생합니다. 만약 유효한 요청이라면 원래 요청으로 보내려던 요청을 다시 요청하여 리소스를 응답받습니다.

CORS 에러 해결 방법

정석적인 방법 : 서버에서 해결하기

동작원리를 보면, 서버에서 Access-Control-Allow-Origin 헤더에 유효한 값을 포함하여 응답을 브라우저로 보내면 CORS 에러를 해결할 수 있다. 프론트단에서 CORS 에러를 발견했다면 서버에게 Access-Control-Allow-Origin에 유효한 값을 포함해서 달라고 요청해야 한다.

와일드 카드격인 * 를 사용하여 Access-Control-Allow-Origin에 헤더를 세팅하면 모든 출처에서 오는 요청을 받겠다는 의미이므로 당장은 편하겠지만 보안적으로 심각한 이슈가 발생할 수 있다.

그러니 Access-Control-Allow-Origin:특정주소 와 같이 출처를 명시해줘야한다

헤더는 서버 엔진의 설정헤서 추가할 수도 있지만 아무래도 복잡한 세팅을 하기에는 불편하기 때문에 소스 코드내에서 응답 미들웨어를 사용하여 세팅하는 것을 추천한다고 한다.

Node.js의 Express 는 cors 라는 서드파티 미들웨어를 지원한다고 한다. 이처럼 다른 프레임워크에서도 cors 를 해결해 주는 라이브러리가 존재한다.

프론트 엔드 개발자가 CORS 에러를 확인했다면?

  1. 서버에 Access-Control-Allow-Origin등 CORS를 해결하기 위한 몇 가지 응답 헤더를 포함해 달라고 요청해야 합니다.
  2. 직접 서버 구축
  3. 로컬 한정 http-proxy-middleware 사용하기

배포하기 전 로컬환경 한정일 때 사용하면 좋은 라이브러리이다.

http-proxy-middleware를 설치하고

setupProxy.js 라는 파일을 src 폴더 내에 만들고 아래 코드를 작성해준다.


후기

백엔드쪽에서의 경험은 많이 없지만 CORS의 경우 종종 api를 통해 데이터를 불러오거나 할 때 봤었다.(알라딘 api를 사용해 도서정보를 불러오고, 파이어 베이스를 사용했을 때 cors지옥에 빠졌었다...하하). 그냥 발생하는 에러가 아니라 보안상의 문제로 꼭 지켜야 하는 것이니 이런 문제가 발생할 경우 되도록 서버측과 원활한 소통으로 해결해야하는 것인가 생각이 들었다

0개의 댓글