ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [네트워크] CORS에 대해
    Frontend/Computer Science 2022. 3. 24. 20:13

    지난 포스팅에 same-site와 same-origin 그리고 cross-origin에 대해 다뤄보았다. 

     

    [네트워크] same-site와 same-origin

    프론트를 공부하다보면 CORS 에러를 자주 접하게 된다. CORS는 Cross-Origin Resource Sharing의 약자로 문제를 이해하기 위해 먼저 origin과 site 개념에 대해 정리해보았다. Origin https://www.exameple.com:..

    jihye-dev.tistory.com

     

    바로 CORS를 이해하기 위해 진정 빛을 발하는 것이 same-site와 same-origin 그리고 cross-origin에 대한 기본 개념이다. 

     

     

    CORS가 생긴 배경, SOP

    SOP(same-origin policy, 동일 출처 정책) 어떤 출처(origin)에서 불러온 문서나 스크립트가 다른 출처에서 가져온 리소스와 상호작용하는 것을 제한하는 중요한 보안 방식이다. 동일 출처 정책은 잠재적으로 해로울 수 있는 문서를 분리함으로써 공격받을 수 있는 경로를 줄여준다. SOP은 애초에 다른 사이트와의 리소스 공유를 제한하기 때문에 로그인 정보가 타 사이트의 코드에 의해서 새어나가는 것을 원천적으로 방지할 수 있다. 이러한 보안상 이점 때문에 SOP은 모든 브라우저에서 기본적으로 사용하고 있는 정책이다.

     

     

    CORS란

    웹 어플리케이션은 SOP에 의해 본인의 출처(origin)와 동일한 리소스만 불러올 수 있으며 다른 출처의 리소스를 불러오기 위해서 CORS가 등장했다.  CORS(Cross-Origin Resource Sharing, 교차 출처 리소스 공유)브라우저가 리소스 로드를 허용해야 하는 자체가 아닌 다른 출처를 서버가 나타낼 수 있도록 하는 HTTP 헤더 기반 메커니즘다. 다른 출처의 리소스를 불러오려면 그 출처에서 올바른 CORS 헤더를 포함한 응답을 반환해야 한다.

     

     

    CORS 동작방식

     

    1. Preflight Request

     

    프리플라이트 요청은 실제 요청을 보내기 전, OPTIONS 메소드로 사전 요청을 보내 해당 출처 리소스에 접근 권한이 있는지부터 확인하는 것이다. 이는 실제 요청을 보내기 전에 미리 권한 확인을 할 수 있기 때문에, 실제 요청을 처음부터 통째로 보내는 것보다 리소스 측면에서 효율적이다.

     

    예를 들어 클라이언트는 preflight를 사용하여 DELETE 요청을 보내기 전에 서버에서 DELETE요청을 허용할지 묻는다.

     

    OPTIONS /resource/foo
    Access-Control-Request-Method: DELETE
    Access-Control-Request-Headers: origin, x-requested-with
    Origin: https://foo.bar.org

     

    서버가 허용하면 다음 Access-Control-Allow-Methods을 나열하는 응답 헤더로 DELETE 요청에 응답한다.

     

    HTTP/1.1 204 No Content
    Connection: keep-alive
    Access-Control-Allow-Origin: https://foo.bar.org
    Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE
    Access-Control-Max-Age: 86400

     

    2. Simple Request

    단순 요청은 특정 조건이 만족되면 프리플라이트 요청을 생략하고 요청을 보내는 것을 말한다. 아래의 조건을 만족하는 경우에만  프리플라이트 요청을 생략할 수 있다.

    • GET, HEAD, POST 요청 중 하나여야 한다.
    • 자동으로 설정 되는 헤더 외에, Accept, Accept-Language, Content-Language, Content-Type 헤더의 값만 수동으로 설정할 수 있다.
      • Content-Type 헤더에는 application/x-www-form-urlencoded, multipart/form-data, text/plain 값만 허용된다.

     

    3. Credentialed Request

    다른 출처 간 통신에서 보안을 강화하고 싶을 때 사용하는 방법으로 요청 헤더에 인증 정보를 담아 보내는 요청이다. 출처가 다를 경우에는 별도의 설정을 하지 않으면 쿠키를 보낼 수 없다. 이 때 요청에 인증과 관련된 정보를 담을 수 있게 해주는 옵션이 바로 credentials 옵션이며 프론트, 서버 양측 모두 CORS 설정이 필요하다.

    • 프론트 측에서는 요청 헤더에 withCredentials : true 를 넣어줘야 한다.
    • 서버 측에서는 응답 헤더에 Access-Control-Allow-Credentials : true 를 넣어줘야 한다.
    • 서버 측에서 Access-Control-Allow-Origin 을 설정할 때, 모든 출처를 허용한다는 뜻의 와일드카드(*)로 설정하면 에러가 발생한다. 인증 정보를 다루는 만큼 명시적 URL을 설정해주어야 한다.

     

     

    해결방안

     

    서버에서 Access-Control-allow-origin 헤더 추가

    서버에서 Access-Control-allow-origin에 명시적 URL을 설정해야한다.

     

    webpack-dev-server proxy

    프론트엔드에서 webpack-dev-server proxy 기능을 사용하면 서버쪽 코드를 수정하지 않고 해결 할 수 있다.

    webpack-dev-server의 프록시를 사용하면, 브라우저에서 API를 요청 할 때 백엔드 서버에 직접적으로 요청을 하지 않고, 현재 개발서버의 주소로 요청을 하게 된다. 해당 요청을 받아 그대로 백엔드 서버로 전달, 백엔드 서버에서 응답한 내용을 다시 브라우저쪽으로 반환한다.

     

     

    참고자료

    https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

    https://velog.io/@jesop/SOP%EC%99%80-CORS#corscross-origin-resource-sharing-%EA%B5%90%EC%B0%A8-%EC%B6%9C%EC%B2%98-%EB%A6%AC%EC%86%8C%EC%8A%A4-%EA%B3%B5%EC%9C%A0

    https://medium.com/@x24mak/cross-origin-resource-sharing-cors-275e52b021b8

    https://evan-moon.github.io/2020/05/21/about-cors/

    https://xiubindev.tistory.com/115

    반응형

    댓글

Designed by Tistory.