CORS 원인 및 해결방법

Developer:Bird·2020년 10월 18일
13

WEB

목록 보기
1/4

CORS (Cross-Origin Resource Sharing)

[개요]

🚨 Access to fetch at ‘https://api.lubycon.com/me’ from origin ‘http://localhost:3000’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.

다음과 같은 오류가 발생하면 바로 CORS가 발생한것인데 웹개발자라면 한번쯤은 겪어봤을것이다.
웹사이트의 URL을 다음과 같이 표현할 수 있다.

이때, Origin=Protocol+Host이다.
즉 CORS란 서로 다른 Origin(웹어플리케이션)에서 리소스에 접근할때 발생하는 오류이다.
예를들면 naver.com 에서 google.com에 있는 resourse에 접근하는경우 이다.

[원리]

웹 클라이언트 어플리케이션이 다른 출처의 리소스를 요청할 때는 HTTP 프로토콜을 사용하여 요청을 보내게 되는데, 이때 브라우저는 요청 헤더에 Origin이라는 필드에 요청을 보내는 출처를 함께 담아보낸다. 이후 서버가 이 요청에 대한 응답을 할 때 응답 헤더의 Access-Control-Allow-Origin이라는 값에 “이 리소스를 접근하는 것이 허용된 출처”를 내려주고, 이후 응답을 받은 브라우저는 자신이 보냈던 요청의 Origin과 서버가 보내준 응답의 Access-Control-Allow-Origin을 비교해본 후 이 응답이 유효한 응답인지 아닌지를 결정한다.

[방식]

1.Simple Request

2.Preflight Request:예비요청

브라우저는 요청을 한번에 보내지 않고 예비 요청과 본 요청으로 나누어서 서버로 전송한다.

이때 브라우저가 본 요청을 보내기 전에 보내는 예비 요청을 Preflight라고 부르는 것이며, 이 예비 요청에는 HTTP 메소드 중 OPTIONS 메소드가 사용된다. 예비 요청의 역할은 본 요청을 보내기 전에 브라우저 스스로 이 요청을 보내는 것이 안전한지 확인하는 것이다.

RSS 파일 리소스에 요청을 보내면 브라우저가 본 요청을 보내기 전에 OPTIONS 메소드를 사용하여 예비 요청을 보내는 것을 확인할 수 있다

3.Credentialed Request

3번째 시나리오는 인증된 요청을 사용하는 방법이다. 이 시나리오는 CORS의 기본적인 방식이라기 보다는 다른 출처 간 통신에서 좀 더 보안을 강화하고 싶을 때 사용하는 방법이다.

이것을 구성하는 옵션에는 총 3가지의 값을 사용할 수 있으며, 각 값들이 가지는 의미는 다음과 같다.

옵션
(1)same-origin (기본값):같은 출처 간 요청에만 인증 정보를 담을 수 있다
(2)include:모든 요청에 인증 정보를 담을 수 있다
(3)omit:모든 요청에 인증 정보를 담지 않는다

만약 same-origin이나 include와 같은 옵션을 사용하여 리소스 요청에 인증 정보가 포함된다면, 이제 브라우저는 다른 출처의 리소스를 요청할 때 단순히 Access-Control-Allow-Origin만 확인하는 것이 아니라 좀 더 빡빡한 검사 조건을 추가하게 된다.

🚨 Access to fetch at ’https://evan-moon.github.io/feed.xml’ from origin ’http://localhost:8000’ has been blocked by CORS policy: The value of the ‘Access-Control-Allow-Origin’ header in the response must not be the wildcard ’*’ when the request’s credentials mode is ‘include’.

브라우저는 인증 모드가 include일 경우, 모든 요청을 허용한다는 의미의 *를 Access-Control-Allow-Origin 헤더에 사용하면 안된다고 이야기하고 있다.

이처럼 요청에 인증 정보가 담겨있는 상태에서 다른 출처의 리소스를 요청하게 되면 브라우저는 CORS 정책 위반 여부를 검사하는 룰에 다음 두 가지를 추가하게 된다.

Access-Control-Allow-Origin에는 *를 사용할 수 없으며, 명시적인 URL이어야한다.

응답 헤더에는 반드시 Allow-Control-Allow Credentials: true가 존재해야한다.

[해결방법]

1. 서버쪽 해결 (response)
HTTP 응답헤더 Access-Control-Allow-Origin : * 혹은 Access-Control-Allow-Origin: 허용하고자 하는 도메인 설정해주기.
일반적으로 Default로 설정되어 있음.

2. 클라이언트쪽 해결 (request)
내가 서버헤더 설정할 수 있는 상황이 아니라면!!
리소스 요청하는 서버 사이에 프록시 서버를 하나 거쳐서 요청,응답을 주고 받기.

프록시 서버 : 브라우저와 서버를 통신하는 과정 중간에서 정보교환을 도와주는 중간 서버 ( 브라우저 - 프록시 서버 - 서버 )
프록시 서버는 헤더를 추가하거나 요청을 허용/거부하는 역할을 중간에서 해줘서 Access-Control-Allow-Origin : *의 헤더를 담아 응답해준다!

아무래도 중간단계가 있기 때문에 속도가 느려지는 단점이 있다.

참고출처:
1.https://velog.io/@kimtaeeeny/CORS-%EC%99%80-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-express-proxy-FE-study8

2.https://evan-moon.github.io/2020/05/21/about-cors/#cors%EB%A5%BC-%ED%95%B4%EA%B2%B0%ED%95%A0-%EC%88%98-%EC%9E%88%EB%8A%94-%EB%B0%A9%EB%B2%95

profile
끈임없이 발전하자.

0개의 댓글