Closed kanglocal closed 4 months ago
Protocol + Host + Port 가 같으면 동일 출처라고 한다.
다른 출처 요청일 경우, CORS 정책에 준수하여 요청해야만 정상적으로 응답을 받습니다.
기본적으로 동일 출처 요청(Same-Origin Policy)만 자유롭게 요청이 가능하며 동일 출처 정책이라고 한다. 기준을 완화하여 다른 출처 요청도 할 수 있도록 기준을 만든 체제가 다른 출처 정책(Cross-Origin Policy)이다.
웹 애플리케이션이 다른 출처의 리소스에 접근할 수 있도록 브라우저에서 제공하는 보안 기능입니다. 웹 애플리케이션이 자신의 출처(도메인, 프로토콜, 포트)와 다른 출처의 리소스에 접근하려고 할 때, CORS 정책이 적용됩니다.
CORS의 동작 원리 프리플라이트 요청 (Preflight Request): 브라우저는 실제 요청을 보내기 전에 OPTIONS 메서드를 사용하여 서버에 프리플라이트 요청을 보냅니다. 서버는 이 요청에 대한 응답으로 허용된 메서드, 헤더 등을 명시한 Access-Control- 헤더를 반환합니다. 실제 요청 (Actual Request): 서버가 프리플라이트 요청을 승인하면, 브라우저는 실제 요청을 보냅니다. 서버는 실제 요청에 대한 응답으로 다시 Access-Control- 헤더를 포함시켜 응답을 반환합니다.
CORS란? CORS란 Cross-Origin Resource Sharing의 약자로, 우리말로 직역하면 교차 출처 리소스 공유라는 뜻입니다. 의미 그대로 서로 다른 출처에서 리소스를 공유하는 것을 CORS라고 합니다. 한 출처에 있는 자원에서 다른 출처에 있는 자원에 접근하도록 하는 개념입니다. 웹 애플리케이션을 만들 때, 출처가 다른 자원들을 가져와 사용해야 하는 경우 CORS 설정이 필요합니다. 이러한 설정은 자원을 제공하는 백엔드 서버에서 허용된 출처라고 명시해 주면 됩니다.
필요한 설정을 하지 않은 채 서로 다른 출처에서 리소스를 공유하려고 하면 브라우저에서 동일 출처 정책에 따라 허용되지 않은 교차 출처 리소스 공유에 대해 CORS 에러가 발생할 수 있습니다.
CORS 경험 (진짜 간단ㅜ ㅜ) mypetlog.site의 소셜 로그인을 구현할 때, 리디렉션 URI를 www.mypetlog.site 로 설정하여 도메인이 서로 일치하지 않아 CORS에러가 발생했습니다.
⇒ mypetlog.site로 통일하여 해결했습니다
CORS
CORS 에러
경험
먼저, CORS는 Cross Origin Resource Sharing(교차 출처 리소스 공유)의 약자로, 서로 다른 도메인 간에 자원을 공유하는 것을 의미한다. 한 도메인의 웹 페이지가 다른 도메인의 리소스에 액세스 할 수 있게 하는 보안 매커니즘을 말한다.
웹 브라우저에서 웹 사이트가 로딩되는 과정에 대해 생각해보자.
프론트엔드 서버: https://my-service.com/
백엔드 서버: https://my-service-api.com/
위와 같은 서버 주소를 사용한다고 했을때, 웹 브라우저의 기본 정책은 자바스크립트 코드를 받아온 곳(프론트엔드 서버)에만 자바 스크립트로 추가적 리소스를 요청할 수 있다.
그런데 백엔드 서버에서 리소스를 받아오려고 하면 다른 도메인이기 때문에 오류가 발생하는 것이다. 이러한 정책을 SOP(Same-Origin Policy)라고 한다. 여기서 Origin은 리소스를 접근하는데 사용한 URL의 프로토콜 + 호스트 이름 + 포트 번호의 조합을 뜻한다. 프론트엔드 서버와 백엔드 서버는 호스트 이름이 다르기 때문에 SOP을 위반한다.
그럼 다른 Origin에서 리소스를 받아오는 것은 불가능한 일일까? 이것도 가능하다. 다른 Origin에서 리소스를 받아오려면 리소스를 제공하는 서버(백엔드 서버)에서 CORS를 허용하면 되는데 즉, 서버에서 프론트엔드 서버 Origin에 대한 CORS(교차 출처 리소스 공유)를 허용한다고 설정하면 되는 것이다. CORS를 따로 설정하지 않으면 CORS 에러가 발생한다.
CORS 에러를 허용하는 방법은 언어와 프레임워크에 따라 다르다.
https://chromewebstore.google.com/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf
프록시 사이트 이용 프록시(Proxy)란 클라이언트와 서버 사이의 중계 대리점 개념인데, 프론트에서 직접 서버에 리소스 요청을 했더니 서버에서 따로 설정을 하지 않아 CORS 에러가 발생하면, 모든 출처를 허용한 서버 대리점을 통해 요청을 하는 것이다. 다만 현재 무료 프록시 서버 대여 서비스들은 모두 악용 사례 때문에 api 요청 횟수 제한을 두어 실전에서 사용하기에는 무리가 있다고 한다. 실전에서는 직접 프록시 서버를 구축하여 사용해야 한다.
서버에서 Access-Control-Allow-Origin 헤더 세팅 직접 서버에서 HTTP 헤더 설정을 통해 출처를 허용하게 설정하는 가장 정석적인 해결책. 서버의 종류에 따라 해결책도 다르니 각 서버의 문법에 맞게 HTTP 헤더를 추가해주면 된다.
위클리 과제 수행 도중에 로컬에서 API 테스트 중 CORS 에러 발생 -> 백엔드 쪽 헤더 세팅 변경 요청할 수 없는 부분 -> 크롬 확장프로그램을 통해 해결
CORS란 Cross Origin Resource Sharing의 약자로 출처가 다른 자원들을 공유한다는 뜻입니다. 한 출처에서 다른 출처로 자원을 요청하도록 허용하도록 하는 것이 CORS입니다.
url 중 http + domain + port이 같으면 동일한 출처입니다.
단순요청 조건
브라우저는 다른 출처에 자신의 주소를 origin에 담아서 요청을 보냅니다. 서버는 요청을 확인하고 접근이 가능하다는 access-control-allow-origin에 대항 주소를 담아서 결과를 return 합니다.
preflight는 OPTIONS 메서드로 요청을 보내 서버와 브라우저가 통신하기 위한 통신 옵션과 안정성을 확인합니다. 서버가 어떤 method, header, content-type을 지원하는지 알 수 있습니다. 단순요청이 아닌 요청은 모두 preflight입니다.
요청헤더 origin : 어디서 요청을 했는지 서버에 알려주는 주소 access-control-request-method : 실제 요청이 보낼 HTTP 메서드 access-control-request-headers : 실제 요청에 포함된 header
응답헤더 access-control-allow-origin : 서버가 허용하는 출처 access-control-allow-methods : 서버가 허용하는 HTTP 메서드 리스트 access-control-allow-headers : 서버가 허용하는 header 리스트 access-control-max-age : 프리 플라이트 요청의 응답을 캐시에 저장하는 시간
다른 출처 사이의 통신에서 보안을 강화하고 싶을 때 사용하는 방법으로, 헤더에 인증 정보를 담아 요청을 보냅니다. 기본적으로 출처가 다른 경우에는 쿠키나 인증 관련 헤더(헤더에 Authorization 항목이 있는 요청)를 보낼 수 없습니다. 민감한 정보이기 때문이다. 때문에 그것이 가능하도록 하려면 프론트와 서버 양측 모두 CORS를 설정해야 한다.
서버에서 할 일
CORS란 Cross Origin Resource Sharing. 하나의 출처(Origin = 프로토콜+도메인+포트번호)에서 실행중인 웹 애플리케이션이 다른 출처의 리소스에 대해 HTTP 요청을 통해 접근하고자 할때, 추가 HTTP 헤더를 이용해 리소스 접근 권한을 부여하도록 브라우저에 알리는 매커니즘
즉 CORS 에러란 HTTP 요청을 받는 서버측이 요청을 보낸의 출처의 해당 리소스 접근에 대한 요청을 허락하지 않아서 브라우저에서 접근할 수 없다는 에러를 띄웠다는 것을 의미.
기본적으로 HTTP 헤더를 이용해 HTTP 요청을 보낸 출처와 동작을 허용하거나 제한한다.
직접 해결 경험 로컬에서 테스트시 CORS에러가 나서 백엔드에 localhost:3000을 Access-Control-Allow-Origin에 포함시켜달라고 요청하여 해결
📎 질문
CORS가 뭐죠? CORS를 겪고 직접 해결해 본 경험이 있으면 말해주세요
✏ 구술 답변 키워드
✏ 서술 답변
CORS란?
요약 : 프로토콜, 호스트, 포트 세가지가 동일한지 확인 -> 동일하면 같은출처로 인정(Same Origin). 동일하지 않으면 교차출처(Cross-Origin)요청을 실행.
Cross-Origin Resource Sharing
한 도메인에서 로드되어 다른 도메인에 있는 리소스와 상호작용할 수 있는 체제.
웹 애플리케이션은 리소스가 자신의 출처와 다를 때 교차 출처 HTTP요청을 실행한다.
복잡한 애플리케이션의 경우 클라이언트 측 코드에서 서드파티 API 및 리소스를 참조하는 경우가 많기 때문에 유용하다.
클라이언트 브라우저에서 데이터를 전송하기 전에 서드파티 서버를 확인하여 요청 승인 여부를 확인할 수 있다.( 이게 무슨말이죠?? )
과거 크로스 사이트 요청 위조(CSRF)로 보안상의 취약점이 발견되어 오늘날 브라우저에서는 클라이언트가 클라이언트의 URL과 동일한 오리진의 리소스로만 요청을 보낼 수 있다.
클라이언트 URL의 프로토콜, 포트 및 호스트 이름은 모두 클라이언트에서 요청하는 서버와 일치해야한다.
동일 오리진 정책이란?
기준URL : 'http://store.aws.com/dir/page.html'을 기준으로 아래 이미지 확인하기.
같은 출처에서만 리소스를 공유할 수 있다는 규칙을 가진 정책.
동일 오리진 정책은 매우 안전하지만 실제 사용 사례에는 유연하지 못하다.
브라우저는 동일 출처 정책을 지키고 있다.
따라서 브라우저에서 어떤 API를 호출할 때에는 CORS에러가 발생하지만, 다른 서버에서 같은 API를 호출할 때에는 에러가 발생하지 않을 수 있다.
크로스 오리진 리소스 공유란?
크로스 오리진 리소스 공유는 동일 오리진 정책을 확장한 것이다.
외부의 서드파티와 승인하에 리소스를 공유하려면 CORS가 필요하다.
크로스 오리진 리소스 공유의 작동 원리
현재 브라우저 URL = 현재 오리진
서드파티 URL = 크로스 오리진
크로스 오리진 요청-응답 프로세스는 다음과 같다.
서버에서 크로스 오리진 액세스를 허용하지 않는 경우에는 오류 메시지로 응답한다.
크로스 오리진 리소스 공유 예제
Origin: https://news.example.com
이렇게 되는거겠죠??Access-Control-Allow-Origin: https://news.example.com
Access-Control-Allow-Credentials : "true"
로 응답한다.다른 출처 요청 정책 3가지
단순 요청
프리플라이트 요청(Preflight Request)
요청 순서
인증 정보 요청
Access-Control-Allow-Methods 와 Access-Control-Allow-Headers 의 값을 지정해야 할 경우 와일드카드(*)를 사용하지 않는다.
CORS 경험
URL 미리보기 기능구현 시 겪었다.
proxy 서버를 설정하여 해결했다.
해당 기능 스크린샷
해당 기능 코드
에러 상황 설명
listywave.com
인데, 가져오려는 url은https://example.com
이어서 호스트부터 다르기때문에 CORS에러가 발생한다.해결 방법
const response = await fetch('https://example.com')
을 요청하지않고,const response = await fetch(
/api/getOgDataProxy?url=${encodeURIComponent('https://example.com')});
이렇게 프록시서버에 요청을한다."proxy": "http://localhost:3000",
listywave.com이 어쨋든 localhost 이므로 동일오리진이어서 문제가 되지않는다.프록시가 받아온 정보에서 ogData만 뽑아서 listywave.com에게 다시 전달해준다.
proxy서버 외에도 CORS를 해결하는 방법이 있다!?
대충 아래와 비슷하게 설정해두는듯하다.