Web

CORS

nameless1004 2024. 7. 18. 11:44

CORS란

  • CORS(Cross-Origin Resource Sharing)는 출처가 다른 자원들을 공유한다는 뜻.
  • 다른 출처에 있는 자원을 요청하면, 이를 교차 출처 요청이라고 한다.
  • 기본적으로 동일한 출처의 리소스와 상호작용 하도록 허용.
  • 브라우저의 Web API인 XMLHttpRequest와 Fetch 역시 동일 출처 정책을 따른다. 그래서 다른 출처에서 리소스를 가져오기 위해서는 그 출처에서 CORS 헤더를 포함한 응답을 반환해야 한다.

what is 출처(Origin)?

  • 어떤 웹 콘텐츠에 접근하려고 할 때 사용하는 URL의 프로토콜, 도메인, 포트번호를 Origin이라고 함
  • 따라서 프로토콜+호스트+포트가 같으면 동일 출처라고 한다.
* 동일 출처 예시
http://example.com:80
http://example.com
HTTP 기본 Port인 80번이 생략되어 있으므로 동일 출처이다.
http://example.com/app1/index.html
http://example.com/app2/index.html
오리진이 같으며, Path부터 다르므로 동일 출처이다.
*다른 출처 예시
http://example.com/app1
https://example.com/app2
프로토콜이 다르다.
http://example.com
http://www.example.com
http://myapp.example.com
Host가 다르다.
http://example.com
http://example.com:8080
 포트가 다르다.

다른 출처 요청일 경우, CORS 정책에 준수하여 요청해야만 정상적으로 응답을 받을 수 있다.

다른 출처 요청 정책

다른 출처 요청 정책은 3가지가 있다.

  • 단순 요청(Simple Request)
  • 프리플라이트 요청(Preflighted Request)
  • 인증정보요청(Credential Request)

1. 단순 요청(Simple Request)

  • GET, HEAD, POST 요청만 가능
  • Accept, Accept-Language, Content-Language, Content-Type과 같은 CORS 안전 리스트 헤더 혹은 User-Agent 헤더만 포함가능
  • Content-Type 헤더는 아래 세 종류만 가능
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain
  • ReadableStream 객체가 사용되지 않음
  • XMLHttpRequest 객체를 사용하여 요청하면, 요청에서 사용된 XMLHttpRequest.upload에 의해 반환되는 객체에 어떠한 이벤트 리스너도 등록되지 않는다.

출처: https://escapefromcoding.tistory.com/724

브라우저는 다른 출처에 자신의 주소를 origin에 담아서 요청을 보낸다. 서버는 요청을 확인하고 다른 출처 주소에 접근이 가능하다는 access-control-allow-origin에 해당 주소를 담아서 결과를 리턴한다.

 
 

access-control-allow-origin

액세스를 요청하는 애플리케이션 또는 소스가 응답 콘텐츠에 액세스 할 수 있는지 여부를 명시하는 HTTP 응답 헤더이다.

모든 출처를 허용과 특정 출처 허용으로 나뉜다.

모든 출처 허용은 값에 *를 넣어준다.

특정 출처 허용은 값에 특정 주소를 넣어준다.

2. 프리 플라이트(Preflight Request)

  • 프리 플라이트는 OPTIONS 메서드로 HTTP 요청을 미리 보내 실제 요청이 전송하기에 안전한지 확인.
  • 다른 출처 요청이 유저 데이터에 영향을 줄 수 있기 때문에 미리 전송한다는 의미이다.

요청 헤더에 다음 값이 포함

  • origin: 어디서 요청을 했는지 서버에 알려주는 주소
  • access-control-request-method: 실제 요청이 보낼 http 메서드
  • access-control-request-headers: 실제 요청에 포함된 header

응답 헤더에는 다음 값이 포함

  • access-control-allow-origin: 서버가 허용하는 출처
  • access-control-allow-methods: 서버가 허용하는 http 메서드 리스트
  • access-control-allow-headers: 서버가 허용하는 header 리스트
  • access-control-max-age: 프리 플라이트 요청의 응답을 캐시에 저장하는 시간

출처: https://escapefromcoding.tistory.com/724

3. 신용 요청(Credentialed Request)

  • 쿠키, 인증 헤더, TLS 클라이언트 인증서 등의 신용정보와 함께 요청
  • CORS 정책은 기본적으로 다른 출처 요청에 인증정보 포함을 허용하지 않는다.
  • 요청에 인증을 포함하는 플래그가 있거나 access-control-allow-credentials가 true로 설정한다면 요청할 수 있다.

출처: https://escapefromcoding.tistory.com/724

  • 서버 응답에 access-control-allow-crendentials 가 true가 아니거나 access-control-allow-origin 헤더에 있는 값이 허용된 출처가 아니라면 아래와 같이 오류가 발생

출처: https://escapefromcoding.tistory.com/724

해결방법

서버에서 직접 제어하기

  • 서버에서 Access-Control-Allow-Origin 헤더에 클라이언트 출처를 허용
  • Open API를 사용할 때 처럼 서버를 직접 제어할 수 없는 경우에는 사용할 수 없다.

프록시 서버 사용

  • CORS 정책은 브라우저에서 강제하는 방법이다.
  • 서버 간 통신에서는 SOP 정책이 적용되지 않으므로 프록시 서버를 사용하자
    • 클라이언트에게 응답을 보낼 때 Access-Control-Allow-Origin의 출처로 요청 도메인의 출처를 포함시켜주면 되기 때문에 CORS 문제를 해결할 수 있다.
 
 

SOP(Same-Origin Policy)

웹 생태계에서 다른 출처로의 리소스 요청을 제한하는 정책 중 하나로, 같은 출처의 리소스만 공유할 수 있도록 제한하는 정책

정리

  • 웹브라우저에서 외부 도메인 서버와 통신하기 위한 방식을 표준화한 HTTP 헤더 기반 메커니즘
  • 서버 쪽에서 클라이언트를 대상으로 리소스 허용 여부를 결정하는 방법
  • 같은 origin에서 ajax를 시도 시 CORS 문제가 발생하지 않는다.
  • 클라이언트는 서버가 어떤 origin 요청을 허용하는지는 알 수 없다
  • CORS를 해결하려면 두 가지 방법이 있다.
    • 서버에서 직접 제어 가능한 경우 Access-Control-Allow-Origin 헤더에 클라이언트 출처를 허용
    • 서버에서 직접 제어가 불가능한 경우 프록시 서버를 사용

참고 글

https://velog.io/@kansun12/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-CORS

https://escapefromcoding.tistory.com/724

https://velog.io/@jaewan/WEBSOP% EC%99%80-CORS