icon

메티의 블로그

CORS

CORS

Tags
Network
날짜
Jan 13, 2023
상태
공개
  • CORS 간단 요약
      1. 하나의 클라이언트는 다른 사이트에서 리소스를 요청하려면, 일반 요청에 비해 지켜야 할 것이 있다. CORS 요청은 특별한 헤더가 추가된다.
      1. 다른 사이트의 구분은 프로토콜, 도메인, 포트로 한다.
      1. 다른 사이트 리소스 요청은 안전한 요청과 안전하지 않은 요청 두가지로 분류하고, 안전하지 않은 요청의 경우 브라우저가 preflight 요청을 추가적으로 하게된다.
      1. 다른 사이트 리소스 요청을 하기 위해서는 서버에서 허용을 해주어야하고, 이에 맞추어 클라이언트에서도 대응하여야 한다. (대부분의 책임은 서버쪽이다.)
      1. 쿠키를 사용하기 위해선 credential 관련 옵션도 서버에서 허용해주어야 한다.
 

 
  • SOP : Same-Origin-Policy
    • 하나의 클라이언트는 하나의 Origin 에서만 리소스를 요청하도록 하는 정책, 아무 것도 설정하지 않을 시, 기본 정책
    • Origin
      • Origin 은 브라우저가 request 시에 넣는 헤더 중 하나로, 요청을 보내는 웹 사이트의 프로토콜, 도메인, 포트번호를 보내게 된다.
        Origin 의 구분은 URL의 Scheme (프로토콜), Host (도메인), Port (포트번호)으로 한다.
        Origin의 비교는 브라우저가 한다. 브라우저에 따라서 비교로직이 다를 수 있다.
         
  • 예전에 javascript 에서 request 를 보내던 방법
    • fetch api 를 제공해 주기 전 javascript 에서는 다른 origin 에 요청을 보낼 때, 다음과 같은 방법을 사용했다. 다른 origin 에 요청하는 것 자체가 허용되지 않았었기 때문이다.
    • form
      • form 은 어디에든 데이터를 전송할 수 있었기 때문에, form 태그와 iframe 태그를 이용해서 우회
    • script
      • script 태그의 src 속성은 도메인에 대한 제약이 없었기 때문에, 이를 통해 우회
         
      위 두가지 방법을 사용한 요청은 안전한 요청으로, 다음과 같은 제한사항이 있었다.
      1. 안전한 메소드: GET, POST, HEAD 메소드
      1. 안전한 헤더: Accept, Accept-Language, Content-Language,
        1. Content-Type 헤더 값이 application/x-www-form-urlencoded, multipart/form-data, text/plain 인 경우
      두 조건을 모두 만족해야만 한다.
 
  • CORS : Cross-Origin-Resource-Sharing
    • CORS 요청은 앞서 설명한 안전한 요청과 안전하지 않은 요청이 구분되어 요청 방식이 다르게 동작한다.
       
      1. 안전한 요청
        1. 안전한 CORS 요청 시, 브라우저는 origin 을 알려주는 Origin 헤더를 추가해서 서버에 전송한다. 그러면, 서버는 Access-Control-Allow-Origin 이 있는지 확인해서, 서버가 해당 origin 의 요청을 허용하는지 확인한다. 일반적으로 요청의 Origin 헤더의 값과 응답의 Access-Control-Allow-Origin 의 값이 같거나 * 이면 허용한다고 본다. 이렇게 CORS 요청이 이뤄진 경우, 자바스크립트는 기본적으로 안전한 응답 헤더에만 접근 할 수 있다.
           
      1. 안전하지 않은 요청
        1. 안전하지 않은 요청 시, 브라우저는 preflight 요청을 먼저 보내게 된다. 이는 http 의 OPTION 메소드로 요청하며, Access-Control-Request-Method 헤더와 Access-Controll-Request-Headers 헤더를 통해 안전하지 않은 요청의 메소드와 헤더 종류가 서버에서 허용하는 것인지 확인한다.
          이 preflight 요청의 응답으로 다음과 같은 것을 제공받는다.
          Access-Control-Allow-Origin , Access-Control-Request-Method , Access-Controll-Request-Headers , Access-Control-Max-Age
          Max-Age 헤더를 통해 preflight 요청을 브라우저에서 캐시하고, 해당 기간동안 preflight 요청을 생략한다.
 
  • 자격증명
    • 자바스크립트로 CORS 요청을 보내면, 기본적으로 쿠키나 http 인증 같은 자격 증명(Credential)이 함께 전송되지 않는다.
      하지만, 요즘은 쿠키를 아주 많이 사용하기 때문에, credential 한 정보를 추가하고 싶다면 다음과 같이 해야한다.
      fetch('url', { credentials: 'include' }
      위와 같이 요청을 하면, 쿠키가 같이 url 에 전송되며, 응답에도 Access-Control-Allow-Credentials: true 이 추가되어 온다.
       
  • CORS 에러
    • 즉, CORS 에러는 브라우저가 내는 에러이며, Origin 이 다른 요청을 하는 것이 이상하다고 느껴서 내는 것이다. (이거 위험한 요청인 것 같으니 브라우저에서 막아야겠다! 하는 것)
       

연관 포스트