CORS(Cross Origin Resource Sharing)

문혜리·2023년 5월 18일
0

한 사이트에서 주소가 다른 서버로 요청을 보낼 때 이것관련 오류를 접함

  • 프론트에서 API를 call하려고 HTTP 요청을 보냈을 때 미리 어떤 설정을 해주지 않으면 CORS 문제로 막히게 됨
  • 포스트맨이나 스프링 백엔드에서 HTTP로 요청을 보내면 다 되는데 웹사이트에서 (ajax 요청으로) 보내보면 안됨
  • 그럼 어디에서 보낸 요청이 CORS로 막히는가?
    - 웹사이트를 여는 곳, 크롬/사파리 같은 브라우저에서 보낸 것(프론트)
    • 내가 방문한 사이트를 이 브라우저가 못믿어서 api 요청을 브라우저가 막는것

CORS가 생긴 이유:

  • 보통 사이트같은거 방문할 때 토큰 같은 정보가 쿠키에 저장해서 api 요청할 때 실어서 보냄. (로그인 유지)
  • 즉, 인증정보가 크롬에 저장되어있다는 뜻
  • 하지만 만약 피싱으로 인해 인증정보를 빼돌리는 코드가 있는 사이트에 접속하게 된다면, 걔네가 만든 HTML, CSS, 자바 스크립트 코드가 내 브라우저에 받아진다는거라 내 인증정보를 가지고 있는 크롬에게 무슨 짓을 시킬지 모른다는거임 -> 스니핑 같은거 할 수 도 있고
  • 그래서 어떤 사이트에서 다른 사이트로는 요청이 못가게끔 SOP(Same Origin Policy)로 막고 CORS로 풀어주는 것
    *SOP(Same Origin Policy): 동일 출처 정책, 말그대로 동일한 출처, 똑같은 URL끼리만 API등의 데이터 접근이 가능하도록 막는 것
    -> 즉 CORS 관련 오류가 뜨는건 '이게 되게 하려면 CORS를 허용해주게 해라'

What is CORS?:

  • cross origin resource sharing, same origin과는 반대로 다른 출처간에 리소스를 공유할 수 있도록 하는 것
  • 원래는 Single Origin만 가능했었음
  • 어떤 기준을 충족시키면 리소스 공유가 되도록 만들어진 매커니즘
    • 기준: 요청을 받는 백엔드쪽에서 이걸 허락할 다른 출처들을 미리 명시해두면 됨, 아무나 가능하면 일반적으로 별표나 와일드카드로
    • 백엔드 프레임워크 문서 읽어보면 CORS 옵션을 넣는 방법들이 쉽게 마련되어있음
  • 네이버 지도 API 등의 서비스들도 콘솔에 들어가보면 CORS를 지정해줄 수 있는 부분이 있을 것

CORS 동작 과정:

  • 내 웹사이트에서 네이버지도 API로 요청을 보냄 -> 다른 출처한테 보내는 요청이니까 cross-origin 요청인 것
  • 브라우저는 이렇게 cross-origin 요청일때는 header에 origin이라는 것을 추가해서 보냄
    • origin:
      1. 요청하는 쪽의 scheme: 요청하는 자원에 접근할 방법(http, ftp, telnet 등)
      2. 도메인,
      3. 그리고 포트가 담김
        ex) https//test.com:3000 (scheme: http, domain: test.com, 포트: 3000)
  • 이 요청을 받은 네이버 지도 API 서버는 답장의 헤더에 지정된 Access-Control-Allow-Origin 정보를 실어서 보냄
  • 그럼 크롬이 이 둘을 비교하고 origin에 보낸거 출처값이 서버의 답장 헤더에 담긴 Access-Control-Allow-Origin 똑같이 있으면 안전한 요청으로 간주하고, 응답데이터를 받아오게 됨

토큰 등 사용자 식별 정보가 담긴 요청에 대해서는 더욱 엄격

  • 보내는 측에서는 요청의 옵션에 credentials 항목을 true로 세팅해야 하고 받는쪽에서도 아무 출처나 받는게 아니고 보내는 쪽의 출처 - 웹페이지 주소를 정확히 명시한 다음 Access-Control-Allow-Credentials 항목을 true로 맞춰줘야 함

CORS의 2가지 요청

simple request

  • 요청을 보내기는 다 보내는데 통과를 못하면 답장만 못받아오는것

preflight

  • 요청에 의해 서버의 데이터가 바뀔 수 있는 것들이라 요청을 '보내는'것도 일단 허락을 받아야 됨
  • 요청을 사전전달 해보고 서버의 허가가 떨어지면 실제 요청을 보내도록
  • But simple request로 보내는 것들로도 받는쪽에서 신경 안 써놓으면 서버에 저장된 데이터가 변경이 가해질 수도 있음.
    따라서 이 SOP만 믿을게 아니라 개발자 측에서도 그런걸 다 대비해서 서버를 프로그래밍 해야 하는 것

"simple requests"는 다음 조건을 모두 충족하는 요청입니다:

  • 다음 중 하나의 메서드
    • GET
    • HEAD
    • POST
  • 유저 에이전트가 자동으로 설정 한 헤더 (예를들어, Connection, User-Agent (en-US), Fetch 명세에서 “forbidden header name”으로 정의한 헤더)외에, 수동으로 설정할 수 있는 헤더는 오직 Fetch 명세에서 “CORS-safelisted request-header”로 정의한 헤더 뿐입니다.
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type (아래의 추가 요구 사항에 유의하세요.)
  • Content-Type 헤더는 다음의 값들만 허용됩니다.
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain
  • 요청에 사용된 XMLHttpRequestUpload (en-US) 객체에는 이벤트 리스너가 등록되어 있지 않습니다. 이들은 XMLHttpRequest.upload 프로퍼티를 사용하여 접근합니다..
  • 요청에 ReadableStream 객체가 사용되지 않습니다.

출처:

https://developer.mozilla.org/ko/docs/Web/HTTP/CORS
https://www.youtube.com/watch?v=bW31xiNB8Nc

0개의 댓글