Session And Token
Session
Session의 특징
- Session은 특수한 ID 값으로 구성되어 있다.
- Session은 서버에서 생성되며 클라이언트에서 쿠키를 통해 저장된다.
- 클라이언트에서 요청을 보낼 때 Session ID를 같이 보내면 현재 요청을 보내는 사용자가 누구인지 서버에서 알 수 있다. (요청마다 매번 아이디와 비밀번호를 물어볼 필요가 없음)
- Session ID는 데이터베이스에 저장되기 때문에 요청이 있을 때마다 데이터 베이스를 확인해야 한다.
- 서버에서 데이터가 저장되기 때문에 클라이언트에 사용자 정보가 노출될 위험이 없다.
- 데이터 베이스에 Session을 저장해야하기 때문에 Horizontal Scaling이 어렵다.
:::tip Horizontal Scaling? 서버에서 부하를 분산하기 위해서 서버를 수평적으로 확장하는 것을 뜻한다. :::
Token
유저의 정보를 Base 64로 인코딩된 String 값에 저장하는 도구를 뜻한다.
Token의 특징
- Tokend은 Header, Payload, Signature로 구성되어 있으며 Base 64로 인코딩 되어 있다.
- Token은 서버에서 생성되며 클라이언트에서 저장된다. (Session이랑 동일)
- 클라이언트에서 요청을 보낼 때 Token ID를 같이 보내면 현재 요청을 보내는 사용자가 누구인지 서버에서 알 수 있다. (요청마다 매번 아이디와 비밀번호를 물어볼 필요 없음) (Session이랑 동일)
- Token은 데이터베이스에 저장되지 않고 Signature 값을 이용해서 검증할 수 있다. 그래서 검증할 때마다 데이터베이스를 매번 들여다 볼 필요가 없다.
- 정보가 모두 토큰에 담겨있고 클라이언트에서 토큰을 저장하기 때문에 정보 유출의 위험이 있다.
- 데이터베이스가 필요없기 때문에 Horizontal Scaling이 쉽다.
Session Vs Token 비교
비교 요소 | Session | Token |
---|---|---|
유저 정보 저장 위치 | 서버 | 클라이언트 |
클라이언트에서 서버로 보내는 정보는? | 쿠키 | 토큰 |
유저 정보를 가져올 때 데이터베이스를 확인해야 하는가? | O | X |
클라이언트에서 인증 정보를 읽을 수 있는가? | 불가능 | 가능 |
Horizontal Scaling이 쉬운가? | 어려움 | 쉬움 |
JWT란?
- Json Web Tokeno의 약자로 세션과 토큰을 합친 것이다.
- Header, Payload, Signature로 구성되어 있으며 Base 64로 인코딩 되어 있다.
- Header는 토큰의 종류와 암호화 알고리즘 등 토큰에 대한 정보가 들어있다.
- Payload는 발행일, 만료일, 사용자 ID 등 사용작 검증에 필요한 정보가 들어있다.
Signature
는Base64 인코딩된 Header와 Payload를 알고리즘으로 싸인한 값
이 들어있다. 이 값을 기반으로 토큰이 발급된 뒤로 조작되었는지 검증할 수 있다.
Refresh Token & Access Token
- 두 Token ahen JWT 기반이다.
- Access Token은 API 요청을 할 때 검증용 토큰으로 사용된다.
- Refresh Token은 Access Token을 갱신하기 위한 토큰이다.
- Access Token은 만료 시간이 짧고 Refresh Token은 만료 시간이 길다.
- 상대적으로 노출이 적은 Refersh Token의 경우 Access Token을 새로 발급받을 때만 사용되기 때문에 탈취 가능성이 적다.
Token 사용 과정
:::note
- Basic : 실제 인증 정보 사용 (아이디/패스워드)
- Bearer : 토큰 사용 :::
Refresh Token 예제
:::note
- iat : 발급 시간
- exp : 만료 시간 :::
Reference
JWT Token Test Site (opens in a new tab)
딜리버리 앱 프로젝트를 통해 구현해보기
기존의 문제
Retrofit을 통해서 accessToken을 하드코딩 한 후, 서버에 요청을 보내는 방식으로 detail screen을 구현했다. (opens in a new tab) 하지만 이는 accessToken을 매번 재입력해줘야 하며, accessToken이 만료되면 이를 검증해주는 로직이 없다는 문제점이 있다.
이를 해결해주기 위해서 dio 패키지는 실제로 요청을 보내기 전에 dio interperter
를 통해서 Token을 검증해줄 수 있다.
Interceptor: onRequest
dio Interceptor의 onRequest
는 실제로 요청을 보내기 전에 호출되는 함수이다. 이를 통해서 accessToken을 검증해줄 수 있다.
아래 코드와 같이 accessToken임을 알 수 있는 헤더를 추가하고 요청하면 Interceptor에서 실제 accessToken을 넣어준다.
restaurant_repository.dart
Interceptor 사용
restaurant_detail_screen.dart
Reference
에러 처리
401 Error
custom_interceptor.dart