HTTP는 비연결성과 무상태성을 띄는 프로토콜이다. 이게 무슨 말인가? 먼저 비연결성이란, HTTP는 요청에 대한 응답을 처리한 후 바로 연결을 끊는것을 의미한다. 연결이 끊어졌기 때문에, 자연스레 이전 상태에 대한 정보와 현재 상태가 남아있지 않게 된다. 이를 무상태성이라고 한다.
만약 HTTP가 비연결성과 무상태성을 가지지 않는다면 어떨까?
클라이언트가 많아지고 요청을 처리하지 않음에도, 모든 클라이언트들이 서버와 연결을 유지하고 있다면 자원 낭비가 심해질 것이다.
그렇다고 장점만 있는 것은 아니다. 이전의 상태를 기억하지 못하기 때문에 한번 로그인 했더라도, 다음 요청에서는 해당 클라이언트로부터 다시 로그인을 받아야 하는 불편함이 생긴다.
그러나 대부분의 웹 사이트들이 한번 로그인을 하면 그 다음에 요청에서도 로그인 상태가 유지 되어지도록 구현되어 있다. 무상태성을 따르는 HTTP가 어떻게 이런 구현이 가능할까?
바로 HTTP의 비연결성과 무상태성을 보완한 Cookie와 Session이 있기 때문이다.
클라이언트의 웹 브라우저에 저장되는 임시 데이터
사용자의 웹 사이트 로그인 요청 성공에 대한 응답으로 서버는 클라이언트 측에 저장하고 싶은 정보를 응답 헤더 부분의 Set-Cookie
에 Key-Value형식으로 담는다.
이후 쿠키를 저장받은 클라이언트는 요청을 보낼 때마다, 저장하고 있는 쿠키를 요청 헤더 부분의 Cookie
에 담아 보낸다.
서버는 이렇게 들어온 요청의 Cookie
값을 읽어 클라이언트의 정보를 식별할 수 있다.
클라이언트 브라우저에 정보를 담아 저장하는 쿠키는 다음과 같은 단점들이 존재한다.
위에서 알아본 내용과 같이, Cookie를 이용해 개인정보를 담아 주고 받는 것은 보안상 좋지 않다.
Session은 클라이언트의 인증 정보를 클라이언트가 아닌 서버에 저장하여 서버가 관리한다.
사용자의 웹 사이트 로그인 요청 성공에 대한 응답으로 인증 정보는 서버에 저장하고, 클라이언트에게는 식별자인 JSESSIONID
를 응답 헤더의 Set-Cookie
에 담아 보낸다.
이후 클라이언트는 요청을 보낼 때마다, JSESSIONID
를 요청 헤더의 Cookie
에 담아 보낸다.
이렇게 요청 받은 JSESSIONID
를 서버가 유효성을 판단하고 클라이언트를 식별한다.
Session은 각 사용자마다 고유한 세션 ID를 발급하기 때문에, 요청이 들어올 때마다 회원 정보를 확인할 필요가 없다는 장점이 있다.
Cookie
가 탈취 당하더라도 직접적인 정보가 아닌 JSESSIONID
를 가지고 있으므로 직접적으로 유의미한 정보를 가지고 있지는 않다.JSESSIONID
를 이용해 클라이언트인척 위장하여 인증을 받을 수 있다.JWT(Json Web Token)은 인증에 필요한 정보들을 암호화 시킨 토큰을 의미한다.
방식은 Cookie, Session과 동일하게 암호화된 JWT(Access Token)을 응답 헤더에 실어 보낸다. 이 토큰을 클라이언트가 가지고 있다가 서버 요청시 요청 헤더에 담아 보내면, 서버가 토큰을 검증하고 해당 요청을 처리한다.
헤더에는 암호화할 해싱 알고리즘과 토큰의 타입을 지정한다
{
"alg" : "HS256",
"typ" : "JWT"
}
토큰에 담을 정보를 저장하고 있다. 주로 클라이언트의 고유 ID와 유효기간 등이 포함된다.
{
"exp" : 1480849147370,
"uid" : "123141354611",
"username" : "sangyeop"
}
Signature는 앞선 Header와 Payload를 더해 비밀키로 해싱하여 생성한다. Header와 Payload는 단순 인코딩 값이기 때문에 복호화가 가능하지만, Signature는 서버측 비밀키가 유출되지 않는다면, 복호화 할 수 없기 때문에 토큰의 위변조 여부를 확인하는데 사용된다.
JWT는 모바일 앱 환경에서도 잘 동작하며, OAuth의 소셜로그인과 같은 경우에도 다양하게 사용된다.