Backend with Golang

CORS (Cross-Origin Resource Sharing)

아직개구리 2023. 11. 18. 14:53

한 출처에서 실행중인 웹 어플리케이션이 다른 출처의 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제이다. 

 

  • <img>, <video>, <script>, <link >태그의 경우 cross-origin 정책을 지원하며, image의 경우 다른 사이트의 png, jpg 등의 리소스에 접근하는 것이 가능하다.
  • fetch api 등을 사용해서 javascript를 사용해서 요청을 보내는 경우엔, 다른 도메인 서버에 있는 자원을 가져오려고 할 때 에러가 난다. 기본적으로 same origin policy 를 따른다. 동일한 출처에서만 리소스를 공유할 수 있다를 의미한다.
    • 동일 출처가 아닌 경우 접근을 차단하는 이유는? 기존 웹 브라우저는 하나의 서버에 요청해서 서버가 HTML을 반환해주는 동작을 했었기 때문에 다른 도메인에서 접근하는 것은 악의적인 행동으로 간주되었다. 동일 출처 정책으로 웹페이지가 다른 도메인의 리소스에 대해 제한 없이 접근하거나 조작하는 것을 방지할 수 있다. 자바스크립트 엔진 표준 스펙에는 동일 출처 정책이 포함되게 되었다.
    • CORS 가 없다면? 다른 출처의 어플리케이션이 서버와 통신하는 것에 제약이 없으면? 
  • Origin : Protocol + Host + Port protocol, host, port까지 합친 url을 의미한다.
  • CORS는 결국 서로 다른 도메인에서 자원을 주고 받기 위해 만들어진 정책이다. 
  • CORS가 브라우저의 구현 스펙에 포함되는 정책이기 때문에 브라우저를 통하지 않고 서버간 통신을 할때는 적용되지 않는다. (Postman에서는 됐던 이유.) 출처를 비교하는 로직은 서버에 구현된 스펙이 아니라 브라우저에 구현된 스펙이다. 

CORS가 동작하는 원리

  1. HTTP protocol을 사용해서 요청 헤더에 Origin 필드에 요청을 보내는 출처를 담아서 보낸다.
  2. 이후에 서버가 응답을 할 때 응답 헤더의 Access-Control-Allow-Origin이라는 값에 리소스 접근이 허용된 출처를 내려준다.
  3. 응답을 받은 브라우저는 자신이 보낸 origin과 Access-Control-Allow-origin을 비교해서 유효한 응답인지 확인한다. 

Preflight 요청

  • 서버는 예비 요청을 자동으로 보내게 되는데,
    • 브라우저가 resource destination이 실제 request를 accept할 것인가 아닌가를 확인하는 메커니즘이다.
    • OPTIONS는 Access-Control-Request-MEthod와 Access-Control-Request-Headers 에다가 어떤 type의 메소드와 어떤 type의 header를 요청할 때 사용할 것인지 나타낸다.
  • OPTIONS에 대한 대답으로 server에서는 Access-Control-Allow-Methods 에다가 보낼 request가 acceptable한지 아닌지 알려준다.
    • Access-Control-Allow-Headers: 허용되는 헤더들의 목록을 설정한다.
    • Access-Control-Allow-Origin: 허용되는 origin 들의 목록을 설정한다.
    • Access-Control-Allow-Methods 허용되는 메소드들의 목록을 설정한다.
    • Access Control-Max-Age: 예비 요청이 브라우저에 캐시 될수 있는 시간을 초단위로 설정한다.

Header 

  • AllowedHeaders : Access-Control-Allow-Headers 는 [Access-Control-Request-Headers] Access-Control-Request-Headers를 포함하는 preflight request의 응답에 사용되는 헤더로, 실제 요청때 사용할 수 있는 HTTP 헤더의 목록을 나열한다. client가 실제 요청에 사용할 수 있는 header를 나열한다. 
    • Content-type이 Simple Request조건에서 벗어난 경우에, Access-Control-Request-Headers의 값은 브라우저에서 자동으로 입력이 되어 preflight 요청을 보내게 된다. 그리고 preflight 요청에 대한 응답으로 Access-Control-Allow-Headers에 허용되는 header를 담아서 온다. 그리고 나서 실제 요청을 보내게 된다. 
  • ExposedHeaders: 기본적으로 안전 목록에 있는 헤더만 노출된다. 클라이언트가 다른 헤더에 접근할 수 있도록 하려면 Server는 Access-Control-Expose-Headers 헤더를 사용하여 헤더를 나열해야 한다.