CORS, 쿠키 세션, JWT

ㅎㅎ·2023년 9월 8일
0

CORS

  • 한 사이트에서 주소가 다른 서버로 요청을 보낼 때 발생하는 오류, 브라우저(프론트엔드)에서 주소가 다른 외부 사이트로의 요청을 막는다.

왜 있는가

  • 보안: 어떤 신뢰되지 않은 사이트에서 브라우저에 저장된 클라이언트의 정보(쿠키)를 가지고 해당 쿠키를 발급한 서버로 악의적 목적으로 요청을 보내어 응답 결과를 탈취하거나, API를 악용, 남용하는 사례 등을 막기 위해 필요

  • 예를 들어 착한 닷컴 접속 후 로그인 -> 로그인 유지(아이디, 비번) 위한 토큰 정보 브라우저에 저장

    • 이후 알 수 없는 나쁜 닷컴에 접속 -> HTML, CSS, JS 코드가 유저의 브라우저에서 동작함 -> 해당 코드가 브라우저의 정보를 가지고 어떤 행동을 할 지 알 수 없음 -> 인증정보를 가지고 착한 닷컴에 요청을 보내서, 응답 정보를 나쁜 닷컴의 서버가 탈취, 이와 같이 착한 닷컴 API를 악용할 수 있음

    • 브라우저는 이를 방지하기 위해 Same-Origin Policy를 고수

동일한 출처, 똑같은 URL끼리만 API 이용 등 접근이 가능하도록 함


어떻게 동작하는가 ?

  • Cross-Origin Resource Sharing: 다른 출처간에 리소스를 공유할 수 있도록 하는 것, 여기서 출처는 보내고 받는 각각의 위치 즉 웹사이트랑 API의 주소를 가리키며, 리소스는 주고받는 데이터를 가리킴. 예를 들어 내가 구축한 웹사이트와 네이버 API 간 데이터를 주고 받을 수 있도록 허용하는 것

  • 이전에는 서로 다른 출처끼리 요청을 주고받는 건 안되는 게 기본값이었음, 브라우저에서 애초에 금지, 하지만 웹생태계가 다양해지면서 여러 서비스들간 보다 자유롭게 데이터를 주고 받을 필요성이 커짐, 따라서 이걸 "합의된 출처들간에 합법적으로 허용해주기 위해" 어떠 기준을 충족시키면 리소스 공유가 가능하도록 만들어진 메커니즘이 CORS.

  • 어떻게 출처들을 허용하는가?

    • 요청을 받는 백엔드(Spring, Django)에서 요청을 허락할 다른 출처들을 미리 명시해둠. CORS 옵션을 추가하고, 허용할 사이트들을 적어주면, 지정한 사이트에서는 이 서버로 얼마든지 HTTP 요청을 보낼 수 있음. 아무나 보낼 수 있는 요청의 경우 와일드카드를 이용해 모두 허용, 카카오 API를 이용할 때 우리가 kakao developers에 도메인을 등록해주는 것도 이와 같은 이유

    • 브라우저는 다른 출처로의 요청을 보낼 때 요청에 Origin이라는 header를 추가, 요청을 받은 서버는 응답 헤더에 지정된 Access-Control-Allow-Origin 정보를 실어서 보냄, 만약 내 사이트 주소가 요청 서버에 등록된 사이트라면 이 정보에 내 사이트 주소도 담겨 있음. 크롬에서 Origin과 응답 데이터를 비교해서 현재 사이트가 있다면 안전한 요청으로 간주하고 응답데이터를 정상으로 수신함, 만약 허용되지 않은 origin의 요청이라면 응답 데이터를 사용하지 않고 CORS 에러를 띄움.

    • 토큰 등 사용자 식별 정보가 담긴 요청에 대해서는 보다 엄격한 기준을 적용함. 일단 보내는 측에서는 요청의 옵션에 credentials 항목을 true로 세팅, 받는 쪽에서도 아무 출처나 다 허용하는 와일드카드가 아니라 보내는 쪽의 출처(웹피이지 주소)를 정확히 명시한 다음 Access-Control-Allow-Credentials 항목을 true로 맞춰줘야 함

    • GET, POST와 같은 simple request와 달리 PUL이나 DELETE와 같은 요청들은 본 요청을 보내기 전에 Prefligt을 보내서 본 요청이 안전한지 확인하고 허락이 떨어져야 요청을 보낼 수 있음. 서버의 데이터를 변경할 가능성이 있는 요청이기 때문에 요청 자체를 보내기 전에 먼저 허용 여부를 검증함.

출처: 얄팍한 코딩사전


쿠키

  • 사용자의 브라우저에 key-value 형태로 저장되는 작은 데이터 파일
  • 로그인 여부, 방문 기록 등을 저장
  • 브라우저 단위로 생성: 크롬, 사파리 등 각 브라우저마다 다르게 저장, 같은 도메인을 접속하더라도 브라우저가 다르면 이용 X
  • 서버가 만료시간을 설정 가능
  • 상태를 유지할 수 없는 HTTP의 특징을 보완하기 위해 사용자에게 정보를 저장하고 맞춤형 서비스 제공: 장바구니 기능, 로그인 유지 기능, 오늘 이 창을 다시보지 않기 기능 등
  • 동작 방식

  • 쿠키가 탈취 당하면 보안 상 문제가 발생

세션

  • 웹 사이트에 이용되는 사용자 정보를 "서버"에 저장하는 방법
  • 사용자의 "쿠키"에는 세션 ID만 저장하고, 서버의 메모리에 저장한 세션에서 세션 ID와 함께 저장된 사용자 정보를 이용하여 맞춤 서비스 제공
  • 쿠키에 세션 ID 외에 다른 정보는 저장하지 않으므로 탈취 위험, 사용자 정보 노출 위험 등을 감소시킴
  • 단점
    - 유저 정보가 서버에 있기 때문에 처리 속도에 대한 비용 발생
    - 서버 자원을 사용하기 때문에 유저가 많아지면 공간 비용 발생

출처: [10분 테코톡] 디투의 쿠키와 세션


서버의 세션과 웹 브라우저의 sessionStorage는 다른 개념

  • sessionStorage는 클라이언트 측의 웹 브라우저에서 사용하는 웹 스토리지 메커니즘 중 하나인 sessionStorage에 데이터를 저장하는데 사용됩니다. 이것은 서버 세션과는 완전히 별개

  • sessionStorage.setItem: 클라이언트 측에서만 데이터를 유지하며, 브라우저의 세션 동안만 데이터 유지, 새로고침이나 브라우저를 닫으면 데이터가 손실

  • 서버 세션: 서버 측에서 유지되며, 브라우저와는 독립적으로 서버의 상태를 저장합니다. 사용자가 로그인하거나 세션을 시작하면 서버는 해당 세션을 식별하는 정보를 클라이언트에게 부여하고, 이를 사용하여 세션을 관리, 브라우저를 닫아도 세션은 서버에 유지


localStorage와 sessionStorage의 차이


localStorage와 쿠키의 차이


토큰이란?

  • 세션은 사용자에 대한 식별자(sessionId)와 사용자의 정보를 서버의 메모리에 저장함
  • 접속자가 많으면 메모리 부족, 성능 저하 등의 문제가 발생
  • 서버에 문제가 생겨 중단되면 저장 정보가 날아감(메모리의 휘발성)
  • DB, 하드디스크에 저장하는 방법은 처리 속도가 느림
  • 서비스 규모가 커서 서버를 여러 대 두고 로드밸런싱을 하는 아키텍처에서는 각 서버의 세션 정보가 다르므로 세션 유지가 불가능 함(이메일 서버, 로그인 서버 등등)
  • 이러한 문제를 해결하기 위해 토큰이 등장

토큰 동작방식?

  • 서버가 뭔가를 기억하지 않고 그냥 토큰을 발급

  • HEADER, PAYLOAD, SIGNATURE 부분으로 나뉜 JWT 토큰

  • BASE64로 인코딩 하면 JOSN 형식으로 여러 정보가 들어 있음

    • 토큰 발급, 유효기간, 사용자의 닉네임이나 권한여부 등, 이를 Claim이라고 일컬음
  • 메모리나 DB 등에 정보를 저장할 필요가 없음

  • Header에는 type(토큰의 타입, JWT)과 alg(algorithm, hs256.. 등 암호화 방식)

  • alg에는 signature(서명값)을 만든 알고리즘이 저장되어 있음

  • header, payload, 서버에 저장한 암호화 알고리즘 해석값을 이용하면 서명값을 추출할 수 있음

    • 비대칭 암호화로 키를 보르면 해석 불가, 한 글자만 틀려도 암호를 풀 수 없음
    • 서버에서 토큰 정보를 토대로 서버에 저장된 서명값과 해독값이 일치하는지, 유효기간이 남았는지 확인하여 권한 인증
  • 결점

    • 세션은 stateful하여 서버가 모든 사용자의 상태를 기억하고 있기 때문에 사용자를 서버에서 제어 가능, 예를 들어 한 기기에만 로그인 가능하도록 구현하는 기능을 만들 때 PC에 이미 로그인된 사용자라면 모바일로 로그인 진행 시 PC를 로그아웃 시킬 수 있음
    • JWT는 이미 발급한 정보를 서버에서 다시 변경할 수가 없음, 서버에 기록해서 추적하지도 않으며 이미 고정된 값이므로
    • 토큰이 탈취된 경우 무효화 방법도 없음
    • 이러한 점을 보완하기 위해 accesstoken을 발급해 만료시간을 짧게 하여 탈취 위험을 다소 줄임, 대신 refreshtoken을 하나 더 발급해서 상응값을 DB에 저장, 만료시간 이후 요청이 들어오면 refreshtoken의 값과 DB 값을 비교해보고 인증이 완료되면 새로운 ACCESSTOKEN을 발급시킴, REFRESH TOKEN이 유효할 동안은 로그인 유지가 가능하고, 로그아웃 시키려면 저장된 REFRESHTOKEN을 지우면 됨.
    • 유효기간이 남은 ACCESS TOEKN이 탈취당하면 완전한 해결책은 아니지만, 보완책
    • 이러한 점을 고려해서 설계가 필요

    출처: 세션 VS. 토큰! JWT가 뭔가요?

profile
Hello World

0개의 댓글