본문 바로가기

Study/Web programming

Session vs JWT

웹 프로젝트를 진행하던 중 Authentication 부분을 세션을 이용할 지 토큰을 이용할 지에 대해 정하기 위해 자료조사 한 것을 정리해본다.

 

Session과 JWT 모두 HTTP 헤더에 인증정보를 담아서 보내는 방식을 이용한다. 

Session


Client는 로그인할 때 고유한 세션 ID를 부여받고, Server는 해당 ID를 세션 저장소(주로 Redis 사용)에 쿠키 형태로 저장한다. 

인증이 필요한 요청에 대해 Client가 헤더에 쿠키를 실어서 보내고 Server는 이 쿠키를 대조하여 알맞은 정보를 보내는 형태로 동작한다.

 

장점 : 쿠키는 고유값이므로 서버 자원에 접근하기 쉽다.(바로 바로 어떤 사용자인지 알 수 있게 된다.)

또한, 쿠키를 헤더에 담아 보내는 방식이므로 HTTP요청이 노출되더라도 쿠키 자체가 어떤 유의미한 값을 가지고 있지는 않다.

 

단점 : 단, A의 쿠키를 B가 탈취할 경우 B가 A인척하고 요청을 보낼 수 있다. (세션 하이재킹 공격이 가능하다.)

-> HTTPS, 세션의 유효시간을 넣음으로써 어느정도 해결 가능하다.

JSON Web Token


Access토큰을 HTTP헤더에 실어서 서버로 보내는 방식이다.

헤더, payload, verify signature 총 3가지 요소로 만들어지고 헤더와 payload의 경우에는 인코딩만 될 뿐 암호화되지 않는다. 즉 누구나 디코딩할 수 있다. 하지만 verify signature는 ‘비밀키’를 알지 못하면 복호화할 수 없다. 즉, 비밀키를 모르면 토큰을 조작할 수 없기 때문에 다른 사용자가 데이터를 조작하여 인증을 뚫을 수 없는 것이다.

 

로그인할 때 서버에서는 고유한ID값과 기타 정보를 payload에 넣고 토큰 유효기간을 설정한 뒤 암호화 할 비밀키를 이용해 Access token을 client에게 발급한다. client는 해당 토큰을 이용해서 요청이 필요할 때마다 토큰을 헤더에 실어 보내고, 서버는 verify signature부분을 확인하여 조작 여부와 유효기간을 확인하여 검증된 토큰을 가진 사용자면 payload를 디코딩하여 사용자의 ID에 맞는 데이터를 가져온다.

 

예시) 현재 진행중인 프로젝트에서 채팅 기능을 구현중인데, 채팅 시 이용하게 될 nickname 등을 payload에 담아둔다면 토큰에서 해당 nickname을 parsing하여 가져올 수 있다. 

 

장점 : 별도의 저장소를 관리할 필요가 없이 토큰을 검증만하면 되기 때문에 stateless한 서버를 만들 수 있다. 또한 확장성이 좋다.

 

단점 : 한 번 발급된 JWT에 대해서는 유효기간이 지나기 전까지 계속 사용이 가능하게 된다. 

-> 유효기간을 짧게, Refresh token, oauth2

payload는 암호화되지 않기 때문에 사용자의 중요한 정보를 담을 순 없다.

JWT 길이가 길기 때문에(항상 payload 가지고 있기 때문에) 서버의 자원낭비가 발생할 수도 있다.

 

하지만, JWT가 보안이 더 철저하여 사용하는 것이 아니라 현재 한 사용자가 여러 개의 device를 가지고 있기 때문에 multi device에 대한 처리를 해줄 때 토큰 방식이 더 좋다고 하여 요즘 많이 사용한다고 한다.