Don’t worry about failures

CORS에 대해 본문

cs

CORS에 대해

허흥 2021. 6. 20. 12:07
728x90

CORS는 많은 개발자들이 접하는 이슈 중 하나이다.

이번 사이드 프로젝트 하면서도 겪은 아주 흔한 문제이다.

처음에는 단순히 이 문제를 해결하고자 origin을 모두 허용해주는 *를 header에 담아주기만 하고 넘어갔다. 

 

이제는 CORS에 대한 개념을 깊게  파악하고, 필요에 따라 설정을 해주고자 한다.

 

( 주된 내용은 우테코 유튜브 영상을 참고하여 정리하며 기입된 내용입니다.)

 

개념

웹 페이지 상의 제한된 리소스를 최초 자원이 서비스된 도메인 밖의 다른 도메인으로부터 요청할 수 있게 허용되는 구조. - 위키백과 -

 

단순 글로만 보면 무슨 소리인지 잘 모르기 떄문에 조금 더 길게 늘려보겠다.

 

우선 CORS에 대해 알아보기 전 SOP를 살펴보자.

 

SOP(Same Origin Policy)

다른 출처의 리소스를 사용하는 것에 제한 하는 보안 방식 (정책)

 

CORS든 SOP든 Origin이라는 단어가 언급이 된다.

Origin은 출처 즉, 너는 어디서 왔니?

 

 

지금 내가 작성하고 있는 URL을 따온 것이다. URL은 프로토콜, Host, Port(생략됨)에 대한 정보를 가지고 있으면 이에 대한 정보가 하나의 출처가 된다.  

이 출처가 Origin이고 이 Origin이 같아 ? Same Origin이 되는 것이다. SOP는 이렇게 같은 Origin만을 허용을 해준다는 정책이다.

 

( explore의 경우 port는 비교 대상이 아니라고 한다. 따라서 프로토콜과 호스트만 동일하면 같은 Origin으로 판단한다고 한다. )

 

문제 : http://localhost와 동일한 출처인 url

 

1. https://localhost

2. http://localhost:80

3. http://127.0.0.1

4. http://localhost/api/cors

 

 

정답

2, 4번

 

해설 :

1번 - 프로토콜 다름

2번 - 기본 port는 80, 일반적으로는 생략되어 나타내기 때문에 동일한 Origin이다.

3번 - 동일한 ip는 맞지만, 실제로 브라우저에서는 비교하는 값은 string으로 비교하기 때문에 다른 Origin

4번 - /api/cors는 location 즉 위 사진상 path 영역에 해당. 비교대상이 아니다 따라서 같은 Origin

 

WHY SOP ??

상황은 다음과 같다.

위의 상황에서 SOP는 큰 활약을 하게 된다. 

 

헤커가 만들어 놓은 페이지의 origin이 https://hacker.co 라고 해보자. 이 페이지에서 해커는 페이스북으로 접근을 하기 때문에 페이스북은 https://hacker.co라는 Origin으로 파악하게 된다. 이렇게 되면 페이스북의 origin과 다른 origin으로 접근 해오기 때문에 SOP에 위반이 된다. 이에 접근을 거절하게 된다.

 

위와 같은 상황을 방지하고자 SOP에 대한 정책이 나온 것이다. 하지만, 우리는 페이스북 내에서만 페이스북을 사용하지 않는다. 다른 application에서 페이스북에 접근하여 작업한 내용을 페이스북에 업로드도 하고 데이터를 조회해오기도 한다. 

 

SOP의 개념으로만 보면, 이는 절대 불가능하다. 이를 가능하게 해주는 것이 바로 CORS이다. 

 

facebook developer에서 자신의 application에 대해 redirect url 등에 대한 url을 기입해주면, 페이스북은 접근을 허가해주고 해당 origin으로 접근할 시 접근을 가능하게 해준다.

 

이 시점에서 다시 한번 CORS의 정의에 대해서 살펴보자.

CORS ( Cross-Origin Resource Sharing ) 다른 출처의 자원을 공유

이 단어가 이제는 가까워졌다고 생각한다. 의미 그대로 서로 다른 출처를 허가 해주므로써 자원을 공유할 수 있게 해준다. 

 

여기서 반성을 해보자면, 무조건 CORS에 대해 허용해주는 *를 남발하게 되면, 위험에 노출된다는 것을 더 깊이 알게 됐다.

 

이제 본격적으로 CORS에 대해 살펴보자

 

CORS에 대한 중요한 개념을 짚어보면, 

다른 출처 자원을 접근할 수 있는 권한을 부여하도록 브라우저에게 알려주는 체제. 서버에서 브라우저에게 header를 통해 알려준다. 이 개념에 대한 중요한 이유는 아래의 내용을 살펴보며 짚어보겠다.

 

CORS에 대한 시나리오는 총 3종류가 존재한다.

 

1. 단순 요청 (Simple Request )

2. 프리플라이트 (Preflight Request)

3. 인증정보 포함 요청 (Credentialed Request)

 

1. 단순 요청

단어의 의미 그대로 단순하게 요청하고 그에 대한 응답을 통해 브라우저가 판단.

simple Request는 다음 조건을 만족해야한다.

1. GET, POST, HEAD 메서드 중 하나

 

2. Content-type

 2-1 application/x-www-form-urlencoded

 2-2 multipart/form-data

 2-3 text/plain

 

3. header

 3-1 Accept

 3-2 Accept-Language

 3-3 Content-Language

 3-4 Content-Type

 

위의 값에 대해서만 허용해주고, 이를 모두 만족해야 바로 단순 요청을 할 수 있다.

 

2. 프리플라이트

개념은  ' PRE ' 의미에서부터 시작해보자. pre의 의미와 같게 request 하기 '이전'에 CORS 체크를 해줘.

1. request method: options를 통해 다른 도메인의 리소스에 요청이 가능한지 확인

2. 가능하다고 하면 실제 request를 날림

 

위의 방식으로 두번의 요청을 통해 이루어진다. 

 

요청 방식

 

출처 : https://www.youtube.com/watch?v=-2TgkKYmJt4&list=WL&index=45&t=1171s

응답

출처 : https://www.youtube.com/watch?v=-2TgkKYmJt4&list=WL&index=45&t=1171s

 

서버에서 허가해준 Origin, method, header에 대한 정보와 max-age 즉, cache 생명에 대한 정보를 응답으로 보내준다. 

preflight의 경우, 이전에 체크하는 방식이기 때문에  두번의 요청이 간다. 이렇게 계속해서 체크하게 되면, 서버 자원에 있어 부담이 된다. 이를 방지하기 위해 캐쉬를 잡아두고 같은 요청이 오면 허가를 바로 해줌으로써 본 리퀘스트 요청이 들어간다.

 

WHY Preflight??

여기서 의문을 가져보자.

단순 한번의 요청으로 하는 것이 아닌 Preflight를 통해 두번의 요청의 과정을 겪어야하나?

 

답은, 처음에 언급했던 CORS에 대한 주요 개념

" 다른 출처 자원을 접근할 수 있는 권한을 부여하도록 브라우저에게 알려주는 체제 " 에서 알 수 있다.

무슨 말인가하면,

 

CORS 에러를 가지고 delete 요청을 날렸다고 가정을 해보자.

이 요청에 따라 서버에서는 어떠한 상태를 삭제 완료한 후에 클라이언트 쪽으로 응답을 내려준다. 이 응답에 대해 브라우저가 다른 출처 자원을 접근할 수 있는지 없는지에 대해 판단을 하고 에러를 뿜는다. 

 

이미 서버에서는 요청에 대한 처리를 다 완료가 끝났는데, 클라이언트에서 에러를 낸 상황인 것이다. 이렇게 서버와 클라이언트의 싱크가 맞지 않게 되는 상황이 벌어지게 되는 것이다.

 

이 때문에 Preflight가 필요한 것이다.

 

3. Credentailed Request

인증 관련 헤더를 포함할 때 사용하는 요청.

 

클라이언트측 

credentails : include

 

서버측

Access-Control-Allow-Credentials : true

(Access-Control-Allow-Origin: * 불가 )

 

 

참고 자료: 

https://www.youtube.com/watch?v=-2TgkKYmJt4&list=WL&index=45&t=1171s

728x90

'cs' 카테고리의 다른 글

멀티태스킹 멀티프로세싱..  (0) 2024.03.13
쓰레드에 대해  (0) 2024.03.13
Process & Thread  (0) 2021.06.13
컴파일러와 인터프리터  (0) 2021.06.05
cs 기초 ( Intro )  (0) 2021.06.05