JWT를 알기전 Session에 대해 알아보기
👤 → GET : www.somewhere.com→ 🖥️
← ****.html ←
HTTP Header
- 쿠키에 Session Id를 담아서 응답한다.
- 웹 브라우저는 쿠키의 세션 ID를 저장하고 다음 요청에 세션 ID를 가지고 간다.
- 최초의 요청에 생성되고 두번째 요청부터는 세션 아이디를 달고 요청이 간다.
- 서버는 최초의 요청을 받으면 세션을 생성해주고, 세션을 통해 판단한다.
- 서버는 세션을 생성할 때마다 세션을 저장하여 요청의 세션과 비교하여 판단해야한다.
- 세션 ID는 서버쪽에서 세션의 값을 날렸을때 사라지고, 사용자가 브라우저를 종류 시켰을 때 사라진다. 브라우저의 세션은 보통 시간이 30분 지나면 세션값이 사라진다.
세션의 문제점?
세션은 로그인 요청을 할 때 인증을 위해 사용된다.
클라이언트가 최초 요청을 하면 서버는 세션 저장소에 세션 ID를 생성하여 응답을 해줄 때 Header에 세션 ID를 돌려준다.
클라이언트에 세션 ID가 저장되고 로그인 요청을 하면 서버는 DB에서 유저 정보를 확인하고 정상이면 세션 저장소에 해당 세션ID 아래에 유저 정보를 저장한다.
클라이언트가 인증이 필요한 요청을 보내면 서버는 세션을 먼저 찾고, 유저 정보 값을 찾는다. 있다면 DB에서 데이터를 응답 받고 사용자 정보 응답을 클라이언트에게 보낸다.
세션의 문제는
클라이언트가 서버에 요청을 하고 응답을 받을 때, 동시 접속자가 다수 일 경우 부하를 분산시키기 위해 로드 밸런싱을 한다(여러 서버를 구축함). 클라이언트가 같은 서버에게 요청을 주고받을 경우는 상관없는데 로드 밸런싱으로 다른 서버로 가게되면 최초의 요청으로 세션 아이디를 생성해줘야 하는 문제점이 발생한다.
- 스티키 서버를 만들어 두번째 요청은 무조건 첫번째 요청을 보낸 서버로 보낼 수 있도록 만든다.
- 각 서버의 세션 저장소를 복제하여 각 서버에 분포한다.
- 하나의 DB에 세션 값을 저장하여 공유한다.
세션은 서버가 들고 있어서 메모리에 접근하여 가져오는 것이라 빠르다.
근데 세션값을 DB에 넣게 되면 하드디스크에서 찾아야해서 I/O가 일어나 느려진다.
CPU → RAM → HDD
CPU가 데이터를 필요할 때는 먼저 RAM으로 간다. 그 뒤에 하드 디스크에 가서 찾는다. 찾은 값을 RAM에 넣고 CPU 에 전달하여 처리한다. 그 다음 요청 시 RAM에 데이터가 있기에 I/O가 일어나지 않는다. 하드 디스크의 데이터를 찾기 위해서는 풀스캔을 하기 때문에 느리다.
그래서 보통 DB를 안쓰고 메모리 공유 서버를 사용한다.
메모리(RAM) 공유 서버는 RAM만 있어 여기에 세션 값을 저장하여 공유하는 것이 좋다.
Redis 서버가 대표적이다.
JWT를 알기전 TCP를 알아보자
OSI 7계층을 알아야 TCP/IP를 알게되고 TCP를 알아야 보안을 알게되고 보안을 알아야 JWT이 나온지 알 수 있다.
OSI 7계층
예시로, 스타그래프트를 하고 있다고 생각해보자.
응용 계층에서는 스타그래프트를 사용하고 있다는걸 의미한다. 캐릭터가 스킬을 사용하면 스킬을 표현 계층에서 암호화, 압축 등을 한다. 세션 계층에서는 상대방 쪽으로 데이터를 보낼 수 있는지 인증 체크를 한다. 상대방 컴퓨터가 켜져있는지를 체크한다. 인증이 완료되면 전송 계층에서 TCP/UDP 중 어떤것으로 통신할 지 정한다. TCP는 신뢰성 기반, UDP는 신뢰성 없는 빠른 전송 방식이다. 네트워크에서 IP로 공유기를 찾고 공유기에 연결된 목적지를 데이터 링크 계층에서 찾아주고 물리계층은 광케이블과 같은 물리적인 통로로 데이터를 전송한다.
Web은 TCP 통신을 한다.
보안
보안의 3요소
1. 기밀성(Confidentiality)
기밀성이란 특정 정보에 대해서 허가된 사용자 또는 대상에 대해서만 확인이 가능해야 한다.즉, 허가받지 않은 사용자 혹은 대상에 대해서는 접근이 되지 않아야 하며, 만약 접근이 된다면 해당 정보에 대해서는 기밀성이 깨졌다고 한다.
2. 무결성(Integrity)
무결성이란 특정 정보에 대해서 허가된 사용자 또는 대상에 대해서만 수정 및 삭제등 가능해야 한다.즉, 허가받지 않은 사용자 혹은 대상이 특정 정보에 대해서 수정 및 삭제가 되어야 하지 않아야 하며, 만약 수정 및 삭제가 이뤄 진단다면 해당 정보에 대해서는 무결성이 깨졌다고 한다.
3. 가용성(Availability)
가용성이란 사용자 또는 대상에 대해서 특정 정보에 대한 접근 및 사용 필요시 항상 가능해야 한다.즉, 원하는 시간, 환경, 서비스시에 특정 정보를 사용할 수 있어야 하며, 만약 사용이 불가하다면 해당 정보에 대해서는 가용성이 깨졌다고 한다.
문서가 누구로 부터 왔는지 인증 문제
열쇠를 전달하는 문제
RSA 암호화
Public Key - 공개키
Private Key - 개인키
A 사용자가 B 사용자에게 데이터를 전달할 때, 공개키로 데이터를 암호화 한다.
A 사용자와 B 사용자는 모두 개인의 공개키, 개인키를 가지고 있다.
A 사용자가 B 사용자의 공개키를 이용해서 데이터를 암호화하면 B 사용자는 개인키로 복호화 한다.
A 사용자가 개인키를 사용하여 데이터를 암호화하면 타인이 A 사용자의 공개키로 데이터를 볼 수 있다. B 사용자는 A 사용자의 공개키로 복호화 하여 데이터를 확인할 수 있다. A 사용자의 개인키로 암호화 했기 때문에 A 사용자의 공개키로 복호화 할 수 있다는 것은 A 사용자가 전달했다는게 보증된다.
공개키 암호화 → 개인키 복호화 (RSA) : 인증 문제 해결
개인키 암호화 → 공개키 복화화 (전자서명)
A 사용자는 데이터를 B의 공개키로 암호화 하고 A의 개인키로 다시 암호화 하여 보낸다.
B 사용자가 데이터를 A 사용자의 공개키로 열리면 인증이 완료되어 B의 개인키로 확인할 수 있다.
JWT
JWT.IO - JSON Web Tokens Introduction
RFC
RFC 문서로 만들어진 것이 WWW 인터넷이고, 이 약속의 프로토콜이 HTTP 프로토콜이다.
JWT는 RFC 7519에 만들어진 약속이다.
JSON Web Token?
JSON객체로 안전하게 정보를 전송하기 위한 방식이다. 디지털 서명이 되어있어 신뢰할 수 있다.
HMAC 알고리즘 또는 RSA 알고리즘을 사용한다.
JWT는 서명 된 토큰(인증)에 중점을 둔다.
JSON Web Token은 언제 사용하는가?
JSON Web Token 구조
- Header
- Payload
- Signiture
헤더, Header
JSON은 Base64Url 암호화,복호화 할 수 있어 디코딩이 가능하다. Spring 에서 비밀번호를 암호활 할때는 해시를 사용하여 암호화한 할 수 있어 비밀번호 초기화를 해야한다.
{
"alg" : "HS256
"typ" : "JWT"
}
Payload
- Registered claims
- Public claims
- Private claims - 여기에 userId 등 사용자 지정 키-벨류를 넣는다.
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
Signiture
Header, Payload, Key를 HMAC으로 암호화 한다.
secret Key는 서버만 알고 있는 키이다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
클라이언트 → 서버
로그인을 시도할 때 username과 password를 서버로 전달한다.
서버는 Header(HS256), Payload({username : ssar}), Signiture(header + payload + secret→ HS256으로 암호화)을 만들어 각각을 Base64Url로 인코딩하여 클라이언트에 전달한다.
클라이언트는 이 정보를 웹 브라우저의 Local Storage에 저장을 한다.
다시 클라이언트가 서버에 요청을 할 때, Local Storage에 저장된 JWT를 가지고 서버에 요청을 한다. 서버는 JWT를 받아 검증을 한다. 서버는 유효한 토큰인지 확인하기 위해서 header와 payload와 서버가 가지고 있는 secret로 똑같이 HS256으로 암호화를 한다. 클라이언트가 보내준 정보와 암호화한 정보가 같다면 인증을 할 수 있다. Payload에 담겨있던 username을 사용하여 DB에 접근해 클라이언트에게 데이터를 전달해줄 수 있다.
RSA 알고리즘을 사용하면 Signiture를 만들 때 Secret 키를 따로 만들 필요가 없다.
서버는 Header와 Payload를 개인키로 암호화 하여 Signiture을 만들면 된다.
클라이언트가 서버에 요청을 할 때, 서버는 검증을 할 때, 공개키로 서명(인증)을 하면된다.
참고 자료
- youtube - 메타코딩
https://www.youtube.com/watch?v=cv6syIv-8eo&list=PL93mKxaRDidERCyMaobSLkvSPzYtIk0Ah&index=13
'Web' 카테고리의 다른 글
캐시(Cache)와 캐싱(Caching) 정리 from 10분 테크톡 (1) | 2022.03.21 |
---|