Auth(인증)을 통해서 서비스는 유저를 검증할 수 있음. 하지만 이를 위해서 쿠키와 토큰, 세션과 JWT를 알고 적재적소로 적용해야하기 때문에 알아야 해.
Cookie
를 이용해서 서버는 이용자의 브라우저에 데이터를 넣을 수 있어. 왜냐하면 이용자의 관한 것들을 기억하기 위해서 흔적을 남겨두는 행위이기 때문이야. 정보를 담는 그릇 같은 존재!
Cookie
는 도메인에 따라 제한이 있어. ex) 유튜브가 준 쿠키는 유튜브에만 보내지게 됨
쿠키는 유효기간이 있음(서버에 따라 다름)
공간 제약이 있음
Cookie
는 인증 뿐만 아니라, 여러 가지 정보를 저장할 수 있음 ( 하나의 매개체 )
ex) 웹 페이지 번역을 하게 되면, 서버로부터 쿠키가 브라우저로 전달되고 그 쿠키에 해당 번역 정보가 저장이 됨. 그리고 웹페이지에 방문할 때 마다, 그 쿠키의 내용을 서버에 전달하여 지속적인 번역 서비스를 이용자가 제공받게 됨
요청(request)와 응답(response)을 통한 Cookie
의 역할은?
사이트 방문
→ 브라우저는 서버에 request
→ 서버는 response(모든 데이터 + 이용자가 찾던 페이지 정보가 있음)
→ 그리고 쿠키마저도 response에 담겨서 브라우저에 저장
→ 그리고 이용자가 웹사이트에 방문할 때 마다 해당 쿠키도 요청과 함께 보내게 됨
안드로이드앱과 IOS에서는 지원이 되지 않음. 그래서 다음과 같은 Token
을 사용함
서버에 Cookie
대신 Token
을 보냄(안드로이드 및 IOS에서)
Token
은 그냥 이상하게 생긴 string
Cookie
처럼 Token
도 Session DB
로 가서 해당 Token
과 일치하는 유저를 찾아서 확인
서버로 가는 모든 요청이 이전 요청과 독립적으로 다뤄지는 것을 stateless 라고 하는데, 이러한 요청이 끝나면, 서버는 이용자가 누구인지 잊어버림. 그래서 필요한게 Session
.
로그인을 하는 절차는 다음과 같은데,
유저명 그리고 비밀번호를 서버에 보냄
→ 비번이 맞으면, 서버는 Session DB에 유저를 생성
→ 해당 Session에는 별도의 ID가 있음
→ 해당 Session ID는 쿠키를 통해 브라우저로 돌아오고 저장됨
→ 같은 웹사이트의 다른 페이지로 가면 해당 Session ID 쿠키를 서버로 보냄
→
해당 Session ID를 서버가 Session DB로 가져가서 확인
→ 해당 ID가 해당 유저의 것임을 확인
→ 인증완료
→ 같은 웹사이트 다른 페이지로 가도 해당 위의 프로세스가 반복되면서 지속적인 로그인이 가능해짐
현재 로그인한 유저들의 모든 Session ID
를 DB에 저장해야한다는 것을 유념해야 함
그래서 유저의 수가 늘어날 수록 DB가 Scale Out
해야함 ( 비용 증가 )
Session
을 사용하면 서버는 로그인 된 유저의 모든 정보를 저장하여, 해당 정보를 통해서 새로운 기능을 추가할 수 있음 ex) 특정 유저 강제 로그아웃(세션 삭제)
인스타그램의 원하지 않는 디바이스에서 강제 로그아웃
넷플릭스 계정 공유 숫자 제한
주로 Session DB
는 redis
JWT
는 Token
형식. 보통 Session ID 보다 훨씬 길다. (제약이 없기 때문에 한계가 없음)
Session DB
가 필요없음. 암호화도 되어 있지 않음
서버는 유저인증 한다고 DB로 가서 확인하는 등의 작업을 생략해도 됨.
그대신, 싸인 알고리즘
을 통해서 싸인된 로그인 정보
를 string 형태로 유저에게 전달.
→ 동일하게 로그인 할때, 토큰이나 싸인된 정보를 서버로 보내면
→ 토큰의 조작여부과 싸인된 정보가 맞는지 서버는 확인
→ 인증완료
→ 같은 웹사이트 다른 페이지로 가도 해당 위의 프로세스가 반복되면서 지속적인 로그인이 가능해짐
이렇게 서버는 해당 토큰 및 정보가 유효한지만 검증하면 됨!
추가적인 기능을 실현 불가능 Session
과 달리!
ex) 코로나 QR 체크인
JWT는 Header, Payload, Signature 로 구성.
{
"typ": "JWT",
"alg": "HS256"
}
서버에서 첨부한 사용자 권한 정보와 데이터
Payload 부분에는 토큰에 담을 정보가 들어있습니다. 여기에 담는 정보의 한 ‘조각’ 을 클레임(Claim) 이라고 부르고, 이는 Json(Key/Value) 형태의 한 쌍으로 이뤄져있습니다. 토큰에는 여러개의 클레임들을 넣을 수 있습니다.
등록된 클레임(Registered Claim)
공개 클레임(Public Claim)
{
"https://dnjscksdn98.com/jwt_claims/is_admin": true
}
{
"username": "velopert"
}
{
"iss": "dnjscksdn98.com",
"exp": "1485270000000",
"https://dnjscksdn98.com/jwt_claims/is_admin": true,
"userId": "dnjscksdn98",
"username": "alex"
}
위 예시 Payload는 2개의 등록된 클레임, 1개의 공개 클레임, 2개의 비공개 클레임으로 이뤄져있습니다.
서명(Signature)은 토큰을 인코딩하거나 유효성 검증을 할 때 사용하는 고유한 암호화 코드입니다. 서명은 위에서 만든 헤더(Header)와 페이로드(Payload)의 값을 각각 BASE64로 인코딩하고, 인코딩한 값을 비밀 키를 이용해 헤더(Header)에서 정의한 알고리즘으로 해싱을 하고, 이 값을 다시 BASE64로 인코딩하여 생성합니다.
생성된 토큰은 HTTP 통신을 할 때 Authorization이라는 key의 value로 사용됩니다. 일반적으로 value에는 Bearer가 앞에 붙여집니다.
{
"Authorization": "Bearer {생성된 토큰 값}",
}