∞. 기술 면접/2. 네트워크

04. 기술면접 - 네트워크 - CORS

THE HEYDAZE 2021. 9. 30. 09:59
공부목적으로 다른 블로그의 글을 그대로 따라치면서 작성되었습니다. 저작권 문제 시, 비공개 처리하겠습니다

개념

- CORS (Cross Origin Resource Sharing)
  - 웹 서버에게 보안 cross-domain 데이터 전송을 활성화 하는 cross-domain 접근 제어권을 부여한다

- 배경
  - 처음 전송되는 리소스의 도메인(request origin)과 다른 도메인(response orign)으로부터 리소스가 요청 될 경우
     corss-origin HTTP 요청에 의해 요청
  - 보안 상의 이유로, 브라우저들은 스크립트 내에서 초기화되는 cross-origin HTTP 요청을 제한한다
      - 예를 들면 XMLHttpRequest 는 same-orgin 정책을 따르기에 XMLHttpRequest 를 사용하는 웹 애플리케이션은
        자신과 동일한 도메인으로 HTTP 요청을 보내는 것 만 가능했다
      - 순수 Ajax ( XMLHttpRequest ), Jquery Ajax ( $.ajax ), Promise 기반 Ajax (Axios) 
      - 웹 애플리케이션을 개선시키기 위해, 개발자들은 브라우저 벤더사들에게 XMLHttpRequest 가
         cross-domain 요청을 할 수 있도록 요청했고 이에 따라 CORS 가 생겼다
      - 정확히 기존에는 <img src> 라던가 <link href> 라던가 에서는 이미 CORS 를 지원하고 있었고 <script> 단에서도
        CORS 를 허용하게 해달라는 요청이 생겨 서버에서 허용할 때에만 script 에서도 CORS 가 가능해진 것이다

- 과정
    - CORS 요청 시에는 미리 OPTIONS 주소로 서버가 CORS 를 허용하는 지 물어본다
    - 이 때  Access-Control-Request-Method로 실제로 보내고자 하는 메서드를 알리고,
    - Access-Control-Request-Headers 로 실제로 보내고자 하는 헤더를 알린다
    - Allow 항목들은 Request 에 대응되는 것으로, 서버가 허용하는 메서드와 헤더를 응답하는 데 사용된다
    - Request 랑 Allow 가 일치하면 CORS  요청이 이루어진다

Spring (서버)단에서 origin, method, header 에 대해 보안을 적용하고 있다
https://brownbears.tistory.com/336

 

CORS 요청 종류

- Simple RequestPrefligth Request
- Credential Request Non-Credential Request

종류는 위와같이 4가지가 존재하며 4가지 방식 중 해당하는 방식으로 서버에 요청을 날리므로, 프로그래머가 목적에 맞는 방식을 선택하고 그 조건에 맞게 코딩해야 합니다

Simple Request (간단 요청)
: 클라이언트가 서버에 1번 요청하고, 서버도 클라이언트에게 1번 회신하는 것으로 처리가 종료됩니다

[조건]
1. GET, HEAD, POST 방식
2. POST 방식5인 경우 Content-type 이 아래 셋 중의 하나여야 한다
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
3. 커스텀 헤더(내부적인 헤더가 아닌 직접 만든 헤더) 를 전송하지 말아야 한다

 

Prefligth Request (예비 요청)
: Simple Request [조건] 에 해당하지 않으면 브라우저는 Preflight Request 방식으로 요청
: 먼저 서버에 예비요청(Prefligth Request) 을 보내고 서버는 예비 요청에 대해 응답 하고, 그 다음에
  본 요청 (Actual Request) 를 서버에 보내고, 서버도 본 요청에 응답합니다
: 2번 요청 2번 회신
: 예비요청을 보내기 위해서는 OPTIONS 메소드를 활용니다

[조건]
1. GET, HEAD, POST, PUT, PATCH, DELETE, OPTION 등 방식
2. Content-type 에서 application/xml 과 같은 다양한 type 사용
3. 다양한 커스텀 헤더 사용

즉, API 서버에 요청을 보낼 때는 OPTIONS 로 체크한 다음 서버에서 Access Control Allow-메소드명 등을 응답 받은 뒤
현재 보내는 본 요청(GET|POST 등)이 응답 받은 Allow 에 조건에 부합하면 본 요청을 서버에 날린 후 응답을 받게 된다

axios 나, jquery 등 라이브러리 내에서 그런 역할을 처리한건지 아니면 자바스크립트 내장으로 인식하고 있어서 자동으로 option 을 해주는 지는 안찾아봐서는 모르겠다 둘 중 1가지 방법으로 option 을 요청하지않을까 생각된다

 

[TIL] `OPTIONS` 요청은 왜 발생하는가?

웹 개발을 하다 보면 네트워크 요청시 실제 원하는 요청(GET, PUT, POST, DELETE 등)전에 OPTIONS 요청이 발생하는 것을 볼 수 있다. 이게 뭘까하고 응답값을 확인하면 아무것도 없다. 응답값이 없는 이

nukeguys.github.io

 

Request With Credential (자격 증명=인증 이 포함된 요청)
: HTTP Cookie 와 HTTP Authentication 정보를 인식할 수 있게 해주는 요청이다
const xhr = new XMLHttpRequest() 를 이용하여 요청시 xhr.withCredentials = true 를 지정해서 Credential 요청을 보낼 수 있고, 서버는 Response Hanlder 에 반드시 Acces-Control-Allow-Credentails : true 를 포함해야 하고, Access-Control-Allow-Origin 헤더의 값에는 * 은 피해야하고 구체적인 http://foo.origin 과 같은 구체적인 도메인이 와야한다
Credentails 옵션은 true 로 줬는 데 Control-Allow-Orign 의 값을 *로 주면 에러가 발생합니다
그림은 아까위에 Spring 코드를 참고하시면 됩니다

 

Request without Credential (자격 증명=인증 이 포함안 된 요청)
CORS 요청은 기본적으로 Non-Crendential 요청이므로 xhr.withCredentails = true 를 지정하지 않으면 Non-Crendential Rquest 입니다
// 자바스크립트 코드 - 클라이언트에서 서버에 요청하려고 할 때 이런식으로 속성을 정의합니다
const xhr = new XMLHttpRequest()
xhr.withCredentials = true

참고로  클라이언트에서 withCredentials 를 true 를 준다하여도 서버에서 credentials 를 false 를 줬다면 응답(response) 는 브라우저에 의해 무시되어
다음 본 요청을 하게 되는 경우 Request With Crendentail 을 보낼 수 없게 됩니다
-> 이게 인증이 포함이 안된 상태로 본 요청이 나가는 지 아니면 본 요청 자체가 안나가는 지는 시도하지않아서 모르겠습니다

 

결론
CORS 를 쓰면 AJAX 로도 Same Origin Policy 의 제약을 넘어 다른 도메인의 자원을 사용할 수 있음
CORS 를 사용하려면 클라이언트에서는 Access-Control-** 류의 HTTP Header 를 서버에 보내야 하고,
서버도 Acces-Control-** 류의 HTTP Header 를 클라이언트에 회신하게 되어 있어야 한다