CORS 에러 발생 시 해결책

이스·2021년 6월 17일
0

웹 개발을 하다보면 CORS 에러와 자주 마주하게 된다.

CORS는 간단히 얘기하자면, 다른 출처 간 자원 공유가 이뤄질 수 없다는 것이다.
여기서 얘기하는 출처란 scheme, 도메인, 포트 모든 것을 포함한다.

만약 클라이언트를 3000번, 서버를 5000번 포트에 띄웠다면 클라이언트에서 서버를 호출할 수 없는 문제가 발생한다.

따라서, 서버에서 CORS를 허용하는 작업을 따로 해주어야한다.

flask의 경우 flask-cors 라이브러리를 이용하여 해결할 수 있다.

import flask
from flask-cors import CORS

app = Flask(__name__)
CORS(app)

초 심플!


하지만 cookie에 유저 정보를 저장하고 이를 클라이언트 - 서버 간에 주고 받아야 한다면 일이 살짝 복잡해진다.

cross-origin request 경우에 user credentials(cookie 등)의 전송이 제한되어 있기 때문이다. (same-origin의 경우에는 기본적으로 허용되어 있다.)

따라서 user credentials를 전송하겠노라고 별도로 명시해줘야한다.

1. 클라이언트(javascript, axios)

import axios from "axios";

const client = axios.create({
	baseURL: "localhost:5000",
    withCredentials: true,
});

2. 서버(python, flask)

import flask
from flask-cors import CORS

app = Flask(__name__)
CORS(app, supports_credentials=True)

credentials 관련 항목을 모두 true로 설정해주었다.

끝난줄 알았지?

이 상태에서 요청을 보낼 경우 아래와 같은 에러가 발생한다.

Header in the response must not be the wildcard '*' when the request's credentials mode is 'include'

간단히 말하면 credential이 포함된 데이터를 주고받을 때는 'access-control-allow-origin'을 와일드카드(*)로 설정할 수 없다는 것이다.
access-control-allow-origin이 "*"인 경우 서버는 다른 어떤 크로스 도메인으로부터의 요청도 수용한다.

보통의 경우라면 괜찮지만, credentials의 전송을 허용하는 경우에는 임의의 도메인으로부터 요청을 받으면 보안에 취약해질 수 있다.

따라서 요청을 받을 도메인을 한정해야 한다.

실제로 flask-cors docs에도 supports_credentials=True로 설정하기 위해서는 origin이 "*"면 안된다고 나와있다.

아래와 같이 할 수 있다.

import flask
from flask-cors import CORS

app = Flask(__name__)
CORS(app, supports_credentials=True, origins="localhost:3000")

origins에는 string뿐만 아니라 list가 들어갈 수있다.

#cors #credentials

업무 중에 알게 된 사실을 빠르게 적어내느라 일부 내용이 빠져있다.
추후 추가할 내용

  • preflight request
  • jwt 및 jwt 옵션

0개의 댓글