SOP와 CORS

Jeong seulho·2023년 4월 12일
0

중요 지식들

목록 보기
5/15

📌Same-Origin Policy

  • 스크립트 코드는 어디 서버에서 왔는지 출처가 있다
    • 혼자 개발하면 localhost 서버 => live server extension이나 npm run start한 리액트 서버 키면 localhost(내컴퓨터)가 서버가 되어 스크립트 코드가 내 브라우저에 다운로드 되고 실행 됨
    • 구글에 접속하면 google 도메인 서버 => google에 접속하면 google 웹서버로 부터 온 스크립트 코드가 내 브라우저에 다운로드 되고 실행 됨
  • 스크립트 코드가 브라우저에서 실행될 때, 스크립트의 출처(스크립트를 가져온 서버)와 요청할 출처(요청한 서버)가 다르면 SOP정책에 위반 된다
  • 즉, 동일한 출처에 대해서만 리소스 접근을 허용하는 정책

❓출처란?

  • 브라우저마다 다를 수 있지만 대부분 protocol(scheme) + host + port의 일치여부를 판단합니다.
  • 동일 출처 비교 예시

📖CSRF 공격 예시(CSRF 토큰으로 방어 필요)

  1. 해커는 악성 웹사이트를 만듭니다, 이때 이 웹사이트의 코드에 다음과 같은 부분이 있습니다.
<!-- 페이스북에 나는 바보다라는 글을 쓰게되는 코드 -->
<form action="http://facebook.com/api/content" method="post">
    <input type="hidden" name="body" value="나는 바보다." />
    <input type="submit" value="Click Me"/>
</form>
  1. 유저는 페이스북에 로그인이 되어있는 상태여서 브라우저에 로그인 토큰 또는 세션ID를 보유하고 있습니다
  2. 유저는 이 웹사이트에 접속하여 저 form 태그를 제출하게 됩니다
  3. 페이스북은 유저가 로그인된 상태에서 "나는 바보다."라는 글을 써돌라는 요청을 받습니다

📌Cross Origin Resource Sharing

  • 서로다른 출처간에도 요청과 응답을 일부분 허용하는 정책
  • 즉, SOP를 위반해도 CORS을 지키면 허용하겠다

📖기본 로직

  1. 웹에서 다른 출처로 리소스를 요청할 때, HTTP 프로토콜의 Origin이라는 필드에 요청을 보내는 출처를 담는다
  2. 서버에서는 응답시 HTTP 프로토콜의 Access-Control-Allow-Origin이라는 필드에 값을 담아 응답한다
  3. 브라우저에서는 본래의 Origin과 Access-Control-Allow-Origin를 비교하여 이 응답이 유효한지 판단합니다
  • 구체적으로는 다음 3가지 시나리오가 존재

📖Preflight Request

  • 예비 요청과, 본 요청을 나누어서 통신
  • 요청 메소드가 GET, POST가 아닌 OPTIONS
  • 예비 요청
    • Origin 헤더에 자신의 출처를 넣는다.
    • Access-Control-Request-Method 헤더에 실제 요청에 사용할 메소드를 설정
    • Access-Control-Request-Headers 헤더에 실제 요청에 사용할 헤더들을 설정
  • 예비 요청 응답
    • Access-Control-Allow-Origin 헤더에 허용되는 Origin들의 목록을 설정한다.
    • Access-Control-Allow-Methods 헤더에 허용되는 메소드들의 목록을 설정한다.
    • Access-Control-Allow-Headers 헤더에 허용되는 헤더들의 목록을 설정한다.
    • Access-Control-Max-Age 헤더에 해당 예비 요청이 브라우저에 캐시 될 수 있는 시간을 초 단위로 설정한다.
  • 브라우저는 보낸 요청과 응답해준 정책을 비교하여 판단
  • 캐시되어 있는 동안은 예비 요청없이 캐시 응답 사용

📖Simple Request

  • 예비 요청 생략 후 바로 본 요청
  • 예비 요청을 생략할 수 있는 조건(simple request가 될 수 있는 조건)
    • 요청 메소드가 GET, HEAD, POST 중 하나
    • Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width를 제외한 헤더를 사용하면 안된다.
    • Content-Type 헤더가 application/x-www-form-urlencoded, multipart/form-data, text/plain중 하나
  • 대부분 HTTP API 요청은 text/xml 이나 application/json 으로 통신하기 때문에 3번째 Content-Type이 위반되기 때문에, 대부분의 API 요청은 그냥 예비 요청(preflight)으로 이루어진다 라고 이해

📖Credentialed Request

  • 인증된 요청은 클라이언트에서 서버에게 자격 인증 정보(Credential)를 실어 요청할때 사용되는 요청
  • 자격 인증 정보란 세션 ID가 저장되어있는 쿠키(Cookie) 혹은 Authorization 헤더에 설정하는 토큰 값
  • 예비 요청도 원래 있어야 하나 생략함
  • 요청
    • 브라우저의 쿠키와 같은 인증과 관련된 데이터를 함부로 요청 데이터에 담지 않도록 되어있다, 이걸 담도록 하기 위해 credentials 옵션을 설정 해줘야함
  • 응답 : 서버도 마찬가지로 이러한 인증된 요청에 대해 일반적인 CORS 요청과는 다르게 대응
    • 응답 헤더의 Access-Control-Allow-Credentials 항목을 true로 설정해야 한다.
    • 응답 헤더의 Access-Control-Allow-Origin 의 값에 와일드카드 문자("*")는 사용할 수 없다.
    • 응답 헤더의 Access-Control-Allow-Methods 의 값에 와일드카드 문자("*")는 사용할 수 없다.
    • 응답 헤더의 Access-Control-Allow-Headers 의 값에 와일드카드 문자("*")는 사용할 수 없다.
  • 즉, 전부를 통칭하는 별표가 아닌 구체적인 값들을 넣어야함

📌CORS에러 해결 방법

📖백엔드에서 해결

  • 서버에서 Access-Control-Allow-Origin 헤더 세팅 : 백엔드 코드(spring, express.js 또는 웹서버인 apache, Nginx 또는 WAS인 Tomcat에서도 세팅 가능)

📖프론트에서 해결

  • 프록시 서버 사용 및 직접 구축
    • 프록시(Proxy) : 클라이언트와 서버 사이의 중계 대리점이라고 보면 된다.
    • 모든 출처를 허용한 서버 대리점을 사용

  • http-proxy-middleware 라이브러리 사용 등

0개의 댓글

관련 채용 정보