2024. 7. 2. 23:24ㆍCS/백엔드
HTTP - Stateless
HTTP는 Stateless 프로토콜이다. 연결을 유지하지 않고 요청과 응답을 주고받으면 연결을 끊고 다시 요청할 일이 생기면 연결을 새로 구축하는 특성을 가지고 있다는 뜻이다.
대부분의 웹은 HTTP, RESTful API 서버를 사용할텐데 그럼 서버가 클라이언트의 정보를 기억할 방법이 없다. 특히 한 번 로그인한 사용자는 계속 로그인이 유지되어야 하는데 서버 입장에서는 요청하는 클라이언트가 DB의 어떤 사용자인지 구분할 방법이 없다. 로그인을 하던 안 하던 해당 페이지에 접근하는 요청은 GET /url HTTP/1.1 이기 때문이다.
아래의 방식처럼 url로 로그인 정보를 넘겨줄 수도 없고 어딘가에 로그인 정보를 숨겨서 로그인을 유지할 수는 있겠지만 수많은 단점을 가지고 있다.
https://www.google.com/?userid=user&&passwd=userPasswd
이 문제를 해결하기 위해 도입된 것이 쿠키이다.
쿠키와 HTTP Header
웹 브라우저에서 서버로
POST /login HTTP/1.1
user=홍길동
요청을 보내서로그인을 하면 서버는
HTTP/1.1 200 OK
Set-Cookie: user=홍길동
위의 응답을 보낸다. 그럼 웹 브라우저는 내부의 쿠키 저장소에 user=홍길동을 저장해 둔다. 이제 웹 브라우저는 요청을 보낼 때 마다 쿠키 저장소를 찾아보고 쿠키를 꺼내서 Cookie: user=홍길동 헤더와 함께 요청을 보내게 된다.
실제로는 쿠키의 키로 sessionId, expires, path, domain, Secure 등을 만들고 로그인에 성공하면 쿠키에 sessionId나 인증 토큰을 만들어서 클라이언트로 보낸다.
set-cookie: sessionID=abcd1234; expires=Thu, 13-Jan-2022 00:00:00 GMT; path=/; domain=.google.com; Secure
이런 형태를 가지게 될텐데 하나씩 알아보자.
- expires=Thu, 13-Jan-2022 00:00:00 GMT;
- 서버에서 클라이언트로 쿠키를 응답하면서 expires로 만료 날짜를 지정하거나 max-age로 초단위로도 지정할 수 있다. 만료 날짜를 생략하면 브라우저 종료 시 까지만 유지한다.
- domain=.google.com;
- 쿠키에 domain을 지정할 수 있는데 도메인을 명시하게 되면 명시한 문서 기준 도메인 + 서브 도메인들만 쿠키에 접근할 수 있다. 도메인을 생략하면 현재 문서 기준 도메인에만 적용된다.
- example.org에서 쿠키를 생성한다면 도메인을 지정하면 dev.example.org에서도 접근이 가능하고 지정하지 않는다면 불가능하다.
- path=/;
- 경로도 지정하여 이 경로를 퐇마한 하위 경로 페이지만 쿠키에 접근이 가능하도록 설정할 수 있다. 일반적으로 path=/로 루트를 지정해서 해당 도메인의 모든 하위 경로 페이지에서 접근할 수 있게 한다.
- 쿠키와 관련된 보안
1. Secure : 쿠키는 http, https 구분 없이 전송하는데, Secure를 적용하면 https인 경우에만 전송한다.
2. HttpOnly : XSS 공격 방지, 자바스크립트에서 접근할 수 없다. HTTP 전송에만 사용한다.
3. SameSite : XSRF 공격 방지, 현재 내가 요청하는 도메인과 쿠키에 설정된 도메인이 같은 경우만 쿠키를 전송한다.
세션이란? 쿠키와 세션의 차이점은?
세션은 쿠키를 기반하지만 사용자 정보를 브라우저가 아닌 서버에 저장한다. 웹 서버에 저장되는 쿠키가 세션인 것이고 브라우저 종료시 만료되므로 보안적으로도 좋다. 또 서버 용량이 허용하는 한 데이터를 다 저장할 수 있으므로 용량 제한도 없다.
세션은 각 클라이언트를 고유 Session ID를 부여하여 각 클라이언트에 맞는 서비스를 제공할 수 있다.
즉, 저장 위치가 쿠키는 클라이언트이고 세션은 웹 서버이다. 속도는 쿠키가 더 빠르지만 보안은 세션이 더 좋다고만 기억해 두면 될 것 같다.
JWT 토큰이란?
Json Web Token은 JSON 객체에 인증에 필요한 정보를 담은 후 비밀키로 서명한 토큰이다.
쿠키를 사용하듯이 클라이언트에 토큰을 저장하고 요청 시 HTTP 헤더에 토큰을 포함하여 인증하게 된다.
JWT는 위와 같은 구조를 가진다. 하나씩 알아보자.
- Header
- kid : 서명 시 사용하는 키(Public, Private)를 식별한다.
- typ : 토큰 유형
- alg : 서명 암호화 알고리
- Payload
- 토큰에서 사용할 정보의 조각들인 클레임이 담겨있다.
- 클레임은 Key/Value 형태로 되어있다.
- iss : 토큰 발급자
- sub : 토큰 제목
- iat : 토큰 발급 시간
- exp : 토큰 만료 시간
- roles : 권한
- Signature
- 서버가 내부에 가지고 있는 유일한 key 값을 합친 것을 헤더에서 정의한 알고리즘으로 암호화한다.
- 헤더와 Payload는 단순한 인코딩이라 누구나 복호화할 수 있지만 Signature는 서버의 key가 없으면 복호화할 수 없다.
JWT VS Cookie
JWT (JSON Web Token)
작동 원리:
- 인증 과정: 사용자가 로그인하면 서버는 사용자 정보를 바탕으로 JWT를 생성한다.
- 전송: JWT는 클라이언트에게 전달되고, 클라이언트는 이를 로컬 저장소나 쿠키에 저장한다.
- 요청 시 포함: 클라이언트는 이후 요청 시 JWT를 HTTP 헤더(보통 Authorization 헤더)에 포함시켜 서버로 전송한다.
- 검증: 서버는 전송된 JWT의 Signature를 확인하여 토큰의 무결성을 검증하고, 필요한 경우 Payload의 정보를 사용해 사용자 인증을 처리한다.
쿠키
작동 원리:
- 생성: 서버가 응답 시 Set-Cookie 헤더를 통해 클라이언트에게 쿠키를 생성해 보낸다.
- 저장: 클라이언트는 쿠키를 브라우저에 저장한다.
- 요청 시 포함: 클라이언트는 이후 동일 도메인에 요청할 때 자동으로 쿠키를 HTTP 요청 헤더에 포함시켜 서버로 전송한다.
- 읽기 및 처리: 서버는 요청 시 전송된 쿠키를 읽어 필요한 정보를 처리한다.
아래의 세 그림은 BE_성하 님의 블로그를 참조한 그림인데, 세 그림을 잘 이해해 보자!
'CS > 백엔드' 카테고리의 다른 글
[백엔드] 웹 서버 VS WAS(앱 서버) (0) | 2024.05.05 |
---|