Kraken-Addicts / HTTP-The-Definitive-Guide

HTTP/Network Group Study
36 stars 4 forks source link

Q7) CORS (Interview Question in HTTP) #18

Open 365kim opened 4 years ago

365kim commented 4 years ago

CORS가 무엇인지, 그리고 어떻게 해결을 할 수 있는지 간단하게 설명해주세요

SeongsangCHO commented 4 years ago

즉석 cross origin resource sharing (cors)는 요청과 응답이 다른 주소에서 발생할 때 생기는 이슈입니다 예를들어 같은 ip주소를 사용하는 서버끼리 http요청과 응답은 가능하지만 다른 ip주소를 가진 서버끼리는 브라우저에서 cors정책에 의해 리소스 공유가 막히게 됩니다

원치않는 곳에서 요청이 들어왔을때에 이를 막기위한 개념으로 이해하고 있습니다.

해결법은 요청을 받은 서버에서 요청에 대한 응답으로 set-origin ..머시기 헤더에 요청을 허용할 ip주소를 명시하거나 nodejs에서는 cors패키지를 사용해 허용할 주소를 명시하면 해당 주소에 대한 요청을 응답 할 수 있습니다. (뇌피셜난무)

보충

CORS는 다른 출처간의 리소스 공유를 뜻합니다. 다른 출처란 다른 도메인, 포트번호를 사용하고 있는 것을 뜻합니다.

CORS문제는 다른 출처의 요청을 허용해주는지에 대해 명시하지 않으면 발생합니다. CORS정책을 지키지 않으면 브라우저 상에서 서로 다른 도메인/포트의 서버로 요청이 갈 때 브라우저에서 에러가 발생합니다. 허용하지 않은 다른 출처의 애플리케이션이 사이트간 요청 위조(CSRF cross site request forgery - 공격자가 수정,삭제 등록 등의 특정 요청을 보내는 것)나 XSS(Cross - site scripting - 웹 페이지에 악성 스크립트를 삽입) 등으로 공격할 수 있기에 CORS 정책을 지킨 리소스 요청에 대해서만 출처가 다른 요청을 허용할 수 있습니다.

해결법으로는 Access-Control -Allow-Origin을 서버의 헤더에 세팅하여 출처를 명시하거나 웹팩의 webpack-dev-server을 사용해 리버스 프록시 기능을 사용하는 등의 방법이 있습니다

ku-kim commented 4 years ago

과거에 웹은 단순히 클라이언트의 요청에 따라 특정 서버의 텍스트나 이미지를 제공해주어도 충분했습니다. 하지만 현대에 오면서 웹 서버는 클라이언트에게 한 번에 더 많은 데이터, 서비스를 제공해주기 위해서 자신이 가지고 있는 정보를 넘어 다른 서버의 정보까지 한 번에 보여주려고 했죠. 다시 말해 프론트엔드 서버와 API 서버를 따로 두는것입니다.

클라이언트에게 한 번에 다양한 서버의 정보를 한 번에 보여주는 방법은 2가지가 있습니다.

  1. 프론트엔드 서버가 다른 웹 서버들의 정보를 요청하고 응답받아서 한 번에 데이터를 정리하여 클라이언트에게 보내주는 방법
  2. 프론트엔드 서버는 클라이언트에게 프론트엔드 기본 폼만 보내고 다른 웹 서버들의 정보는 클라이언트가 직접 요청하여 응답받는 방법 1번의 방법도 있었지만 서버 부하와 클라이언트 응답속도가 늦었기 때문에 개발자들은 2번의 방법을 활용하려 했습니다.

하지만 웹브라우저 정책 중 도메인이 다르면 요청을 주고 받을 수 없는 정책이 있습니다. SOP(Same-Origin Policy) 그래서 당시의 개발자들은 이 정책을 우회하는 방법으로 JSONP 라는 방법으로 우회하여 다른 도메인의 정보를 가져왔었지만 이는 공식적인 방법도 아니었고, CSRF(Cross-site request forgery), XSS(cross-site scripting)와 같은 보안 문제가 있었습니다.

시대에 변화에 클라이언트(웹브라우저)는 이를 공식적으로 인정하는 정책을 만들었는데 이것이 바로 CORS(Cross Origin Resuorce Sharing) 입니다. (다른 출처간의 리소스 공유) 따라서 CORS 정책을 따른다면 다른 출처(서버)의 리소스를 요청,응답을 받을 수 있게 되었습니다. CORS 정책은 브라우저의 구현 스팩, 정책 위반 문제이기 때문에 백엔드 개발자가 서버 어플리케이션에서 응답 헤더에 올바른 Acccess-Control-Allow-Origin 이 내려오도록 셋팅 해주면 됩니다. (이는 웹 서버에서 cors 관련 허용을 눌러주면 매우 간단하게 해결? (쿨럭))


추가 내용

같은 출처, 다른 출처, Origin은 무엇일까요?

출처, Origin란 URL의 구성 요소 중 Scheme, Host, Port가 동일해야 합니다. 예를 들어

  1. https://naver.com/about
  2. https://naver.com/about?q=kukim멋져
  3. http://naver.com/about
  4. http://naver.com/:8080 의 URL이 있을 때 1,2번은 동일한 origin이지만 3번은 Scheme가 다름, 4번은 포트번호가 다르기 때문에 다른 출처가 됩니다. (Internet Explorer는 4번의 경우 동일하게 인식하지만..)

웹 클라이언트가 다른 출처의 리소스를 요청

웹 클라이언트(브라우저)가 다른 출처의 리소스를 요청할 떄 HTTP 프로토콜을 사용하여 요청하는데 이때 브라우저는 요청 헤더에 Orgin 이라는 필드에 요청을 보내는 출처를 함께 담아 보낸다. ex) https://www.yebalja.com/jobs 웹사이트에 내용 중 https://www.jobkorea.com/developer/list.js 를 가져온다고 한다면

  1. 클라이언트가 https://www.jobkorea.com/developer/list.js에 요청 메세지를 보냄 (OPTION 메세지, 예비 요청,요청 해도 되는지) 그 헤더에 Origin: https://www.yebalja.com/jobs 를 추가하여 보내는 방식

ex)

OPTIONS https://www.jobkorea.com/developer/list.js

Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,ko;q=0.8,ja;q=0.7,la;q=0.6
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: GET
Connection: keep-alive
Host: www.jobkorea.com
Origin: https://www.yebalja.com/
Referer: https://www.yebalja.com/jobs/1
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
  1. jobkorea 서버는 Option, 예비 요청에 응답해줌 200ok
    
    OPTIONS https://www.yebalja.com/jobs/ 200 OK

Access-Control-Allow-Origin: https://www.jobkorea.com/ Content-Encoding: gzip Content-Length: 699 Content-Type: text/xml; charset=utf-8 Date: Sun, 24 May 2020 11:52:33 GMT P3P: CP='ALL DSP COR MON LAW OUR LEG DEL' Server: Apache Vary: Accept-Encoding X-UA-Compatible: IE=Edge



이때 웹 서버의 요청 응답의
Access-Control-Allow-Origin:  https://www.jobkorea.com/
부분이 Option 요청메세지의 orgin과 달라서 클라이언트(브라우저)가 CORS 정책을 위반했다고 판단하고 에러를 뱉어냄

---
참고
https://www.codecademy.com/articles/what-is-cors
https://evan-moon.github.io/2020/05/21/about-cors/  
https://www.youtube.com/watch?v=yTzAjidyyqs
365kim commented 4 years ago

즉석 다른 도메인으로에도 리소스를 요청할 수 있도록 하는 것입니다.

보충 CORS란 Cross-Origin Resource Sharing의 약자로, 출처가 다른 리소스도 공유할 수 있도록 하는 정책을 말합니다.

보안상의 이유로 원칙적으로는 오직 출처가 동일한 리소스만 공유할 수 있습니다. (Same-Origin Policy) 출처가 동일하다는 것은, 스킴, 호스트, 포트가 모두 동일하다는 말입니다.

하지만 웹에서는 출처가 다른 리소스와의 상호작용이 반드시 필요하기 마련입니다. 따라서 CORS 정책을 지키는 리소스 요청이라면 출처가 다르더라도 허용됩니다.

클라이언트가 요청메세지의 Origin헤더 해당 출처를 적어보내고, 그 응답으로 서보로부터 받은 응답메세지의 Access-Control-Allow-Origin의 내용을 자신이 보냈던 Origin헤더 내용을 비교해본 후 유효한 응답인지 아닌지를 결정하는 메커니즘으로 동작합니다.

terry-yes commented 4 years ago

SOP(Same-Origin Policy) : 서버는 원칙적으로 같은 오리진에서만 오는 요청에 대해서만 응답을 보내줍니다. 여기서 오리진은 같은 프로토콜, 같은 호스트, 같은 포트를 의미합니다. 보통의 클라이언트는 서버와 같은 오리진이 아니지만 단순요청(Simple request)로 분류되어 서버가 응답을 보내줍니다.

하지만 보통의 클라이언트가 아닌 서버가 또다른 서버에게 요청을 보내기도 하는데 이때 CORS가 이용됩니다. 예를 들어 서버 A가 다른 오리진의 서버 B에게 요청을 보낸 경우, 서버 A는 서버 B와 다른 오리진이므로 CORS preflight가 발동되고 서버B에게 option 요청을 보내고 서버B의 허가를 기다립니다. 서버 B는 CORS(Cross-Origin Resource Sharing)를 이용해서 요청을 보낸 서버 A에게 허가를 줄 수 있습니다. 허가는 응답 헤더 중 Access-Control-Allow-Origin: * 헤더의 명시됩니다.

joey-ful commented 4 years ago

CORS(Cross-Origin Resource Sharing)란 다른 출처의 자원에 접근할 수 있도록 허용해주는 브라우저 보안 정책입니다.

SOP(Same Origin Policy)에 의해 서버는 같은 출처에 대한 HTTP 요청에 대해서만 리소스를 보내줍니다. 여기서 같은 출처란 같은 프로토콜, 호스트, 포트를 뜻합니다.

하지만 외부 API를 사용하거나 프론트 서버와 백엔트 서버의 포트를 다르게 사용하는 등 서버를 분리하는 경우에는 다른 출처의 리소스를 가져와야만 하는 상황이 빈번히 발생합니다. 이처럼 클라이언트와 서버의 출처가 다를 때 보안 상의 이유로 응답을 받지 못 하도록 막은 것을 CORS에러라 합니다.

CORS에러를 해결하기 위해서는 서버측에서 Access-Control-Allow-Origin 응답 헤더를 이용하거나 CORS 미들웨어를 사용할 수 있습니다.