세션 인증 방식
- 로그인을 통해 사용자를 확인하고, 사용자 정보를 세션에 저장하여 Session ID를 사용자에게 응답한다.
- 클라이언트는 요청마다 Header에 Session ID가 담긴 Cookie를 넣어서 통신하고,
서버에서는 Cookie를 검증하여 데이터를 응답한다.
JWT 기반 인증 방식 (Json Web Token)

- Claim 기반 방식을 사용한다. (Claim은 사용자에 대한 속성 값)
- 의미있는 토큰(사용자 상태 포함)으로 구성되어 있기 때문에,
AuthServer에 검증 요청을 보내야만 했던 과정을 생략하고, 각 서버에서 수행할 수 있게 되어
비용 절감 및 Stateless 아키텍처를 구성할 수 있다.
동작 과정
- 클라이언트는 Auth Server에 로그인한다
- Auth Server에서 인증을 완료한 사용자는 JWT 토큰을 전달 받는다.
- 클라이언트는 특정 어플리케이션 서버에 리소스를 요청할 때, 전달받은 JWT 토큰을 Authorization Header에 넣는다.
- 어플리케이션 서버는 전달 받은 JWT토큰의 유효성을 직접 검사하여 사용자 인증을 할 수 있다.
특징
- 확장성에 큰 장점이 있다.
- Session : 서버를 확장할 때마다, 각 서버에 세션 정보를 저장해야 한다.
특정 서버에서 로그인 인증을 받을 때, 다른 서버는 로그인했는지 알 수 없다. - JWT : 서버의 수와는 상관없이 토큰을 인증하는 방식을 알고 있으면 인증 과정에 문제가 없다.
- Session : 서버를 확장할 때마다, 각 서버에 세션 정보를 저장해야 한다.
- 웹과 앱 간의 Cookie 세션 처리에도 유용하다.
브라우저와 앱에서의 쿠키 처리 방법은 각기 다를 수 있기 때문에 JWT를 이용하는 것이 다양한 디바이스 차원에서 좋다고 함. - 사용자 인증 정보가 필요한 요청을 보낼 때, 헤더에 JWT 토큰값을 보내기 때문에 데이터가 증가해 네트워크 부하가 늘어날 수 있다.
- 토큰 자체에 사용자 정보를 담고 있기에 JWT가 만료되기 전에 탈취당할 수 있다.
- 한 번 만들어 클라이언트에게 전달하면 제어가 불가능하기 때문에 만료 시간을 필수적으로 넣어줘야 한다.
- 짧은 만료 시간을 같는 JWT 형식의 Access Token과 긴 만료 시간을 갖는 JWT 형식의 Refresh Token 두 가지를 사용한다. ( RefreshToken을 Redis와 같은 DB에 저장하고 새로운 Access Token을 발급받기 위해 거쳐야 하는 추가적인 과정이 생김 )
Access Token과 Refresh Token
- Access Token : 리소스(사용자의 정보)에 직접 접근할 수 있도록 하는 정보만을 가지고 있다. (for 인증)
- 짧은 만료 기간을 가지고, 주로 Session에 담아 관리한다.
- Refresh Token : 새로운 Access Token을 발급 받기 위한 정보를 담고 있다. (for accesstoken 발급)
- 클라이언트가 Access Token이 없거나 만료된 상태라면, RefreshToken을 통해 AuthServer에 요청하여 새로운 AccessToken을 발급받을 수 있다.
- 외부에 노출되지 않게 하기 위해 보통 DB에 저장한다. (필자는 Redis 인메모리 DB에 저장했다.)
서버 간의 통신이 잦은 경우, Access Token을 자주 주고 받을 수 밖에 없다.
- 각 서버는 API 호출 요청에 대해서 전달받은 Access Token이 유효한 지를 확인해야 한다.
- 이는 서버에서 클라이언트의 상태 (=AccessToken 유효성)를 관리하게 한다.
- API를 호출할 때마다, Access Token이 유효한 지 매번 DB에서 조회하고 새로 갱신 시 업데이트 작업을 해주어야 한다.
- 마이크로 서비스 개발처럼, 서버의 수가 많은 경우 각각의 서버가 AccessToken의 유효성 및 권한 확인을 Auth Server에 요청하기 때문에 병목 현상이 발생해 서버 부하로 이어질 수 있다.
+ [프로젝트에서 Access Token과 RefreshToken으로 구현한 로그인 과정을 다른 팀원들에게 설명한 내용]
AccessToken(1시간)과 RefreshToken(2개월)의 유효기간이 실 서비스에서 괄호에 있는 값으로 진행될 예정입니다.
<1시간이 지난 상황>
1시간이 지나면, AccessToken을 재발급하기 위해 'Token 재발급 API'를 프론트에서 서버에 정보를 요청합니다.
요청을 받은 서버에서는 프론트에 200 성공 코드를 보내면서 서버에서는 아직 유효기간이 길게 남은 Redis에 있는 RefreshToken으로부터 AccessToken을 새로 만들어서, header에 X-AUTH-TOKEN에 담아 보내줍니다!
<2개월이 지난 상황>
이제 2개월의 시간이 지나 refreshToken의 유효기간이 만료되면 Redis에 존재하는 refreshToken이 timeout으로 사라집니다. 그 와중에 2달이 지나기전에 발급된 accessToken의 유효기간인 1시간이 만료가 되면, 프론트에 401에러를 보내면서 'Token 재발급 API'를 요청하지만, 프론트가 가지고 온 Cookie에 있는 refreshToken과 서버의 Redis에 저장된 refreshToken을 비교했을때 refreshToken이 이미 사라진 상태이기 때문에 서버 측에서는 프론트에게 로그인 화면으로 전환하도록 401에러를 보냅니다.프론트는 401에러를 보고 사용자가 다시 로그인할 수 있게 로그인 화면으로 전환합니다. 서비스의 유저는 다시 로그인을 하면서 새로운 RefreshToken과 AccessToken을 발급받게 되면서 다시 이 서비스를 이용할 수 있게 됩니다.
'Spring Security' 카테고리의 다른 글
| [로그인 개발 시 필요한] Spring Security 구조 (0) | 2024.02.03 |
|---|---|
| [Spring Security in Action] 책 읽기 (2) | 2024.01.03 |
