등장 배경
브라우저의 개발자 도구를 열면 DOM이 어떻게 작성되어 있고, 어떤 서버와 통신하는지, 리소스 출처는 어딘지 등 여러 정보들을 제한 없이 열람할 수 있다. 사용자가 악의를 가지고 소스 코드를 보면 토큰이나 쿠키 같은 사용자의 정보를 탈취할 수도 있다.
따라서 브라우저는 기본적으로 같은 출처에서만 리소스를 공유할 수 있다는 SOP 정책을 따른다.
근데 이게 개발할 때 불편하기 때문에 SOP의 불편함을 해소하고, 보안을 지키기위해 CORS가 등장한다.
CORS
정의
출처가 서로 다른 서버끼리 리소스를 주고 받을 때 보안을 위해 설정된 정책이다.
출처 판단 기준
https://www.domain.com:3000/category?limit=4¤t_page=1#first
Protocol | Host | Port | Path | Query String | Fragment |
https | www.domain.com | 3000 | category | limit=4¤t_page=1 | first |
프로토콜, 호스트, 포트 3가지만 동일하면 같은 출처이다.
same-origin은 위 3가지가 동일하다는 의미이고,
세 가지 중 하나라도 다르면 cross-origin 이다.
https://www.domain.com |
https://www.domain.com:3000 |
첫 번째 URL에 포트 번호가 포함되어 있지 않기 때문에 이 경우에는 각 브라우저들의 독자적인 출처 비교 로직을 따라간다고 한다.
React 서버를 5000번 포트에 열고, node js 서버를 3000번 포트에 연다고 가정해 보자.
두 서버의 포트 번호가 다르기 때문에 서로 다른 출처로 판단된다.
이때 node js 서버에서 CORS 허용 설정을 안 하면 CORS 위반 에러가 발생한다.
CORS 정책은 언제 검사하는가
출처를 비교하는 로직은 서버가 아닌 브라우저에 구현되어 있다.
- CORS 정책을 위반하는 리소스 요청
- 서버는 정상적으로 응답 (서버가 같은 출처에서 보낸 요청만 받겠다는 로직을 가지고 있지 않다고 가정)
- 브라우저가 응답을 분석해서 CORS 정책 위반일 경우 그 응답을 버린다.
그래서 CORS 정책을 위반하는 리소스 요청이 들어와도 서버 쪽에는 정상적으로 응답을 했다는 로그가 남는다.
기본적인 동작 시나리오
- 웹 클라이언트가 다른 출처의 리소스를 요청할 때
브라우저가 요청 헤더의 Origin이라는 필드에 요청을 보내는 출처를 적는다. - 서버가 요청에 대한 응답을 할 때
헤더의 Access-Control-Allow-Origin이라는 값에 이 리소스에 접근할 수 있는 출처를 적는다. - 응답을 받은 브라우저는 Origin과 Access-Control-Allow-Origin을 비교하여 유효한 응답인지 판단한다.
Preflight Request 방식
현재 구현하고 있는 도서 정보 시스템에서 아래와 같이 헤더의 content type을 application/json으로 설정했기 때문에 프리플라이트 방식으로 동작한다.
export const createClient = (config?: AxiosRequestConfig) => {
const axiosInstance = axios.create({
baseURL: BASE_URL,
timeout: DEFAULT_TIMEOUT,
headers: {
'Content-Type': 'application/json'
},
withCredentials: true,
...config
});
...
return axiosInstance;
}
- 웹 클라이언트가 리소스를 요청한다.
- Origin이라는 필드에 요청을 보내는 출처를 적어서 OPTIONS라는 메소드로 예비 요청을 보낸다.
(예비 요청의 역할은 본 요청을 보내기 전에 이 요청을 보내는 것이 안전한지에 대해 확인) - 서버가 헤더에 허용하는 것에 대한 정보를 적어서 응답으로 보낸다.
- Access-Control-Allow-Origin: 허가된 출처
- Access-Control-Allow-Methods: 허가된 메소드
- Access-Control-Allow-Headers: 허가된 헤더
- Access-Control-Allow-Max-Age: 응답 캐시 유효 시간
- 응답 정보 확인
- 허용되지 않은 요청인 경우 405 Method Not Allowed 에러를 발생시키고, 본 요청은 서버로 전송하지 않는다.
- 허용된 요청인 경우 본 요청을 보낸다.
- & 7. 응답 결과를 받아온다.
+) 프리플라이트 요청 방식은 리소스를 많이 잡아먹기 때문에 서버가 보내준 Access-Control-Max-Age 헤더 정보로 캐싱해서 효율을 높일 수 있다.
'데브코스' 카테고리의 다른 글
[15주차 - DAY1] 도서 정보 사이트 - 도서 상세 페이지 (0) | 2024.06.03 |
---|---|
[14주차 - DAY5] 도서 정보 사이트 - 로그인과 도서 목록 페이지 (0) | 2024.05.31 |
[14주차 - DAY4] 도서 정보 사이트 - 라우팅 (0) | 2024.05.30 |
[14주차 - DAY3] 도서 정보 사이트 - 테마 스위치 (0) | 2024.05.29 |
[14주차 - DAY1] 오픈 소스(5) (0) | 2024.05.27 |