IT Study/CS

[Back] CORS ERROR와 CORS 옵션

짹짹체유 2023. 11. 12. 19:15

 

"우리도 CORS에서 자유롭지는 못했다."

프로젝트를 진행하면서 그전에는 CORS 오류가 나지 않았지만

배포한 후에 CORS 에러가 발생 했고,

그 원인으로는 배포하면서 출처가 다른 url에 대한 설정이 없었기 때문으로 이해를 했었다.

 

 

📍CORS란?

Cross origin Resource Sharing (교차 출처 리소스 공유)

 

" 다른 출처로의 리소스 공유 및 사용 가능 "하도록 하는 메커니즘

 

출처

: 프로토콜(Protocol), 호스트(Host), 포트번호(Port)

   -> 서버 위치를 찾기 위해 필요한 가장 기본적인 것들

 

 

 

출처를 비교하는 로직은 브라우저에서 이루어진다. 브라우저가 CORS 위반 등을 분석한다.

 


📍CORS 이해를 위한 SOP 개념

< 웹에서 다른 출처로부터의 리소스 요청 제한 > 관련한 정책
1. CORS
2. SOP(Same-Origin Policy)
: 같은 출처에서만 리소스를 공유할 수 있다

 

보안상의 이유로 브라우저는 교차 출처 HTTP 요청을 제한한다. CORS 헤더가 없는 경우에는 동일한 출처 내에서만 리소스 요청이 가능하다. 그러나, 실제로는 다른 출처와의 공유가 빈번하. 따라서 같은 출처에서만 리소스를 공유할 수 있는 SOP의 예외 조항으로 CORS가 존재한다. 만약, 'SOP 위반 & CORS 위반' 한다면 다른 출처의 리소스 사용이 아예 불가능한 것이다.

 


📍웹의 리소스 요청과 응답

< Request Headers >

 

웹에서 다른 출처로 리소스를 요청할 때,

브라우저는 HTTP 프로토콜을 통해 Origin 필드에 요청을 보내는 출처를 담는다

우리가 진행한 프로젝트의 클라이언트 포트는 3000번 (localhost:3000) / 서버 포트는 5002번 (localhost:5002)

 

 

< Response Headers >

 

서버는 클라이언트에서 온 요청에 대해 응답을 할 때,

Access-Control-Allow-Origin 필드에 리소스에 접근하는 것이 허용된 출처를 같이 보내준다.

여기서 브라우저는 request한 출처와 서버에서 허용한 출처를 비교해서 동일한지 판별한다.

Access-Control-Allow-Origin의 출처와 request header에 있는 출처가 동일함 -> 요청 가능

 


📍CORS 동작방식

1. Preflight Request (예비 요청)

브라우저는 요청을 보낼 때 예비 요청과 본 요청으로 나누어서 서버에게 보낸다.

본 요청을 보내기 전의 예비 요청이 Preflight Request이다.

예비 요청은 본 요청을 보내기 전에 브라우저가 요청의 안전성을 확인하기 위해 사용한다.

 

CORS 여부를 판단하는 시점은 예비 요청의 응답을 받은 이후이기 때문에, 예비 요청의 성공여부와 크게 상관이 없다.

 

 

2. Simple Request (단순 요청)

단순 요청은 예비 요청 없이 바로 서버에 본 요청을 보내는 방식이다.

특정한 조건들을 만족한다면 예비 요청을 생략하고 단순 요청을 사용할 수 있다.

< 단순 요청 사용 조건 >
1. 요청의 메소드가 GET, HEAD, POST 중 하나
2. 허용 목록에 있는 요청 헤더
- Accpet, Accept-Language, Content-Language, Content-Type, Range
3. Content-Type을 사용할 경우 허용 헤더
- application/x-www-form-urlencoded,multipart/form-data, text/plain

 

3. Credentialed Request

인증된 요청을 사용하는 방법으로 다른 출처 간 통신에서 보안을 강화하고 싶을 때 사용된다.

기존 브라우저는 별도의 옵션 없이 보안 및 인증과 관련한 쿠키 정보 등을 요청 헤더에 담지 않는다.

따라서 Credentails 옵션을 통해서 요청에 인증과 관련한 정보를 담을 수 있게 해준다

 

credentials: true
우리는 쿠키를 사용했기 때문에
서버에서 corsOption으로 credentials를 true로 설정하여
header에 Access-Control-Allow-Credentials를 포함해 쿠키를 주고받을 수 있도록 설정했다.

 


📍CORS 에러를 방지하기 위한 Option

const corsOption = {
  origin: [
    "http://localhost:3000",
    vm 배포를 위한 기타 url들
  ],
  optionsSuccessStatus: 200,
  credentials: true,
  exposedHeaders: ["set-cookie"],
};

app.use(cors(corsOption));

 

 

origin : 리소스를 요청 받을 출처를 명시

optionsSuccessStatus : 요청 응답에 대한 성공 상태코드

      ※   옵션 설정 전,

        - 204 No Content로 설정

      ※   옵션 설정 후,

        -  200 OK로 뜸

 

credentials : 쿠키를 주고받기 위해 true로

exposedHeaders : 콘솔에 데이터가 드러날 수 있도록

 

하나씩 정리하다보니 optionsSuccessStatus와 exposedHeaders 옵션은 굳이?라는 생각이 든다.

 


참고자료

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

https://velog.io/@logqwerty/CORS

https://velog.io/@jh100m1/CORS-%EC%97%90%EB%9F%AC%EA%B0%80-%EB%AD%94%EB%8D%B0-%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%95%B4%EA%B2%B0%ED%95%98%EB%8A%94%EA%B1%B4%EB%8D%B0

 

반응형