CORS란 무엇인가?

Stems·2022년 7월 26일
11

면접

목록 보기
2/2

CORS? ( Cross-Origin-Resource-Sharing )

프로토콜, 도메인, 포트번호가 다른 외부 사이트에 데이터 요청을 했을 때,
보안상의 이유로 브라우저에서 HTTP 요청을 제한하는 것
Protocol - http !== https
Domain - domain.com !== other-domain.com
Port - 8080 !== 3000

👉 이 세가지중 하나라도 다른 경우 cross-origin라 부른다.

ref: https://beomy.github.io/tech/browser/cors/


CORS 가 필요한 이유

모든 곳에서 데이터를 요청할 수 있게 되면 다른 사이트를 흉내내어
기존 사이트와 동일하게 로그인을 하게 만들고, 로그인했던 세션을 탈취하여
악의적으로 정보를 추출하거나 다른 사람의 정보를 입력하는 등 ( XSS, XSRF )
공격을 할 수 있기 때문에 서버에서 동의를 한 경우에만 요청을 수락하고
동의하지 않으면 브라우저에서 거절한다.


URL의 구조

출처 ( Origin )을 살펴보기 위해서 URL 구조를 먼저 살펴봐야 한다.

ref: https://beomy.github.io/tech/browser/cors/


CORS 의 동작

  1. Simple requests
    HTTP method가 다음 중 하나이면서
    • GET
    • HEAD
    • POST
    자동으로 설정되는 헤더는 제외하고, 설정할 수 있는 다음 헤더들만 변경하면서
    • Accept
    • Accept-Language
    • Content-Language
    Content-type이 다음과 같은 경우
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

  1. preflight

  • Origin헤더에 현재 요청하는 origin과, Access-Control-Request-Method헤더에 요청하는 HTTP method와 Access-Control-Request-Headers요청 시 사용할 헤더를 OPTIONS 메서드로 서버에 요청한다. ( 이때 내용물은 없고 헤더만 전송 )
  • 브라우저가 서버에서 응답한 헤더가 유효한 요청인지 확인한 후
    유효하지 않은 요청이면 요청 중단되고 에러 발생.
    유효한 요청이라면 원래 보내려던 요청의 리소스를 응답받는다.
preflight?
Simple requests가 아닌 cross-origin요청은 모두 preflight요청을 하게 되는데,
실제 요청을 보내는 것이 안전한지 확인하기 위해 먼저 OPTIONS 메서드를 사용하여
cross-origin HTTP 요청을 보내는것

HTTP 요청 헤더 목록

요청 헤더들은 별도로 명시해 주지 않아도 브라우저에서 OPTIONS 요청에 추가한다.

🔸 Origin: <origin>
Origin 헤더는 요청하는 대상의 출처를 나타낸다. API를 호출하는 페이지의 출처 값이 저장된다.

🔸 Access-Control-Request-Method: <method>
Access-Control-Request-Method 헤더는 실제 요청이 어떤 HTTP 메서드를 사용하는지 서버에 알려주기 위해 사용된다.

🔸 Access-Control-Request-Headers: <field-name[, <field-name>]
Access-Control-Request-Headers 헤더는 브라우저에서 보내는 커스텀 헤더 이름을 서버에 알려주기 위해 사용된다.


HTTP 응답 헤더 목록

🔸 Access-Control-Allow-Origin: <origin>|*
Access-Control-Allow-Origin헤더에 작성된 출처만 브라우저가 접근할 수 있도록 허용한다.

사용 방법
아래와 같이 응답 헤더가 작성되었다면 https://github.com/kisn3089페이지에서 브라우저는 서버 응답으로 온 리소스를 접근할 수 있다.

Access-Control-Allow-Origin: https://github.com/kisn3089

아래와 같이 *이 작성되었다면, 브라우저는 출처에 상관없이 모든 리소스에 접근할 수 있다.

Access-Control-Allow-Origin: *

🔸 Access-Control-Allow-Methods
브라우저에서 보내는 요청 헤더에 포함된 Access-Control-Allow-Methods 헤더에 대한 응답 결과로, 리소스 접근을 허용하는 HTTP 메서드를 지정해주는 헤더이다.

사용 방법

Access-Control-Allow-Methods헤더에 GET, PUT, POST, DELETE 등의 HTTP 메서드를 , 로 구분하여 넘겨준다.

Access-Control-Allow-Methods: GET, PUT

🔸 Access-Control-Expose-Headers: <header-name>[, <header-name>]*

서버에서 응답 헤더에 Access-Control-Expose-Headers를 추가해 줘야 브라우저의 자바스크립트에서 헤더에 접근할 수 있다.

사용 방법

아래와 같이 , 로 구분하여 여러 개의 헤더를 넣을 수 있다.

Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header

🔸 Access-Control-Allow-Headers: <header-name>[, <header-name>]*

브라우저에서 보내는 요청 헤더에 포함된 Access-Control-Request-Headers헤더에 대한 응답 결과이다.

사용 방법

자바스크립트에서 커스텀 헤더를 서버에 전달하면, OPTIONS요청 헤더의 Access-Control-Request-Headers헤더에 커스텀 헤더 이름이 추가된다. 서버에서는 Access-Control-Request-Headers에 작성된 값을 보고 Access-Control-Allow-Headers응답 헤더에 커스텀 헤더 이름을 명시해 주어야 한다.

Access-Control-Expose-Headers: X-Custom-Request

🔸 Access-Control-Max-Age: <delta-seconds>

preflight 요청 결과를 캐시 할 수 있는 시간을 나타낸다.

사용 방법

아래와 같이 초 단위로 캐시 시간을 설정한다.

Access-Control-Max-Age: 60

위의 코드는 60초 동안 preflight 요청을 캐시 하는 코드이다. 60초 동안 OPTIONS 메서드를 사용하는 예비 요청을 보내지 않는다.

🔸 Access-Control-Allow-Credentials: true

자바스크립트 요청에서 credentialsinclude일 때 요청에 대한 응답을 할 수 있는지를 나타낸다. false로 설정해 주고 싶을 경우에는 헤더를 생략하면 된다.

사용 방법

Access-Control-Allow-Credentials: true

프록시 서버 해결 방법

프론트엔드와 백엔드 사이에 프록시 서버를 두는 방법으로 CORS를 해결할 수도 있다. 개발 환경에서 CORS를 해결해야 한다면, Webpack Dev Server 등의 라이브러리를 사용해서 프록시 설정을 하는 방법도 있다.

profile
- Steadily, Don't Stop

0개의 댓글