웹 개발의 대표 에러 CORS
CORS 는 추가 HTTP 헤더를 사용해서, 한 출처에서 실행 중인 웹 어플이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에게 알려주는 역할이다. 웹 어플은 리소스가 자신의 출처와 다를때 교차 출처 HTTP 요청을 실행하게 된다.
▶ Origin ? (출처)
아까부터 계속 출처가 어쩌구저쩌구 하는데 출처가 뭘까??
위에 그림을 보면 Protocol 과 Host 와 Port 이 3가지가 맨 앞에 있는데 이 3가지가 같은 것을 동일 출처(Same-Origin)이라고 한다 뒤에 나머지는 달라도 상관없지만 앞에 3개가 다르다면 다른 출처라는 뜻이다
▶ SOP(Same - Origin - Policy)
위에서 본것처럼 출처가 굉장히 중요한데 먼저 동일한 출처부터 알아보자 영단어 그대로 뜻은 동일한 출처에 대한 정책을 말한다. 즉, "동일한 출처에서만 리소스를 공유할 수 있다" 라는 뜻이다. 하지만 반대로 출처가 다르다면 원하는 리소스는 가져올수 없다는 것이다.
왜 가져올수 없게 만들어 놓은것일까??
동일 출처가 아닌 경우 즉, 두개의 어플이 자유롭게 소통을 할 수 있는 환경은 매우 위험한 상황이다. 이는 언제든지 해커가 CSRF 나 XSS 등의 방법을 이용해서 우리가 만든 어플에서 해커가 심어놓은 코드가 실행하여 개인정보를 가로채기 때문이다.
▶ CORS (Cross - Origin - Resource - Sharing)
이 문장을 직역하면 교차 출처 리소스 공유 정책이라고 하는데 이말은 출처가 다르다 라는 의미이다. 출처가 다르다는 것은 뭘까?
보다시피 위에서 말한 프로토콜, 호스트, 포트 번호가 동일한것은 모두 같은 출처이고 이 3개중 하나만 달라도 다른 출처가 되는것이다.
▶ 그럼 정확히 차단은 누가 하는걸까
정확히 CORS 에러를 빨간줄로 발생시키는건 누구일까? 바로 브라우저이다. 서버는 요청에 대해 정보를 전달해주었다. 하지만 브라우저가 응답 정보를 받고 동일 출처가 아니면 빨간 에러를 발생 시키는 것이다. 그래서 서버에서는 안정적인 상황인데 오히려 브라우저에서 빨간 오류를 발생시키는 것이다.
그럼 서버잘못??
맞다 서버가 해결을 해주어야 하는것이다. 서버에서 응답하는 CORS 를 따로 설정해주는 것이다.
▶ CORS의 기본 동작
- 클라이언트에서 HTTP 요청의 헤더에 Origin을 담아 전달한다
- 서버는 응답헤더에 Access-Control_Allow_Origin 을 담아서 클라이언트에게 전달한다
- 클라이언트에서 Origin 과 서버가 보내준 Access-Control-Allow-Origin을 비교한다
- 이 과정에서 서로의 Origin이 맞지 않는다면 오류를 내는 것이다.
▶CORS가 작동하는 방식 3가지
- 예비 요청 (Preflight Request)
- 브라우저는 요청을 보낼때 바로 보내는 것이 아니라 예비 요청이라는 것을 전송하여 서버와 잘 통신하는지 확인을 진행한 후에 진짜 요청을 보내게 된다
- 이유는 해당 요청이 브라우저에게 안전한가? 를 확인하기 위해 하는 요청이다.
- 이때 HTTP Method 를 살펴보면 우리가 설정한 GET, POST 가 아닌 OPTIONS 를 사용하고 있다는 것을 알수 있다
- 단순 요청 (Simple Request)
- 단순 요청은 말그대로 예비 요청을 생략하고 바로 서버에 직행으로 보낸 요청을 뜻한다. 서버가 이에 대한 응답으로 헤더에 Access-Control-Allow-Origin 헤더를 보내주면 브라우저가 CORS 정책의 위반 여부를 확인해서 검사하는 방식
- 단순요청은 매우 까다롭다
- 요청의 메소드는 GET, POST, HEAD 중 하나여야만 한다
- Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width 헤더일 경우에만 적용된다
- Content-Type 헤더가 application/x-www-form-urlencoded, multipart/form-data, text/plain 중 하나여야한다. 아닐 경우 예비 요청으로 동작한다
- 이렇게 까다로운 조건때문에 모두 만족하는 경우가 상당히 드물다 심지어 대부분의 HTTP API는 ContentType이 application/json 이다 때문에 거의 없다고 보면 된다
- 인증된 요청 ( Credentialed Request )
클라이언트가 서버에게 자격 인증 정보를 실어서 요청을 할 때 사용되는 요청이다. 여기서 말하는 자격 인증 정보란 세션 ID가 저장되어 있는 쿠키혹은 Authorization 헤더에 설정하는 토큰값 등을 일컫는다.
클라이언트에서 일반적인 JSON 데이터 외에 쿠키 같은 인증 정보를 포함해서 다른 출처의 서버로 전달할때 CORS의 세가지 요청중 하나인 인증된 요청으로 동작된다는 말이며, 이는 기존의 단순 요청이나 예비 요청과는 살짝 다른 인증 형태로 통신하게 된다.
- 서버에서 인증된 요청에 대한 헤더 설정하기
- 서버에서도 이러한 인증된 요청에 대해 일반적인 CORS요청과는 다르게 대응하는데
- Access-Control-Allow-Credentials 항목을 true 로 바꿔주는데 특징이 다른 값에 *(와일드카드문자)를 사용할 수없다 즉, 분명하게 적힌 출처가 있어야한다는 뜻이다 매우 민감한 정보이기 때문이다.
- 클라이언트에서 인증 정보를 보내도록 설정하기
- 기본적으로 브라우저가 제공하는 요청 API들은 별도의 옵션 없이 브라우저의 쿠키와 같은 인증과 관련된 데이터를 함부로 요청 데이터에 담지 않도록 되어있다.
- 요청에 인증과 관련된 정보를 담을 수 있게 해주는 옵션이 바로 credentials 옵션이다. 이 옵션에는 3가지의 값을 사용할 수 있다. 만일 이러한 별도의 설정을 해주지 않는다면 쿠키 등의 인증 정보는 절대로 자동으로 서버에게 전송되지 않는다
- 서버에서 인증된 요청에 대한 헤더 설정하기
'CS > 🖥 네트워크' 카테고리의 다른 글
🖥 TCP 와 UDP의 차이 (0) | 2023.09.16 |
---|---|
🖥 TCP 혼잡 제어(AIMD, Slow Start, Fast Recovery, Fast Retransmit) (1) | 2023.09.16 |
🖥TCP의 흐름제어, 오류제어(Stop-And-Wait, Go-Back-N, Selective Repeat) (0) | 2023.09.16 |
🖥 3-way Handshake / 4-way Handshake (0) | 2023.09.15 |
🖥 RESTful API (0) | 2023.08.03 |