Flutter
이론
Session and Token

Session And Token

Session

Session의 특징

  1. Session은 특수한 ID 값으로 구성되어 있다.
  2. Session은 서버에서 생성되며 클라이언트에서 쿠키를 통해 저장된다.
  3. 클라이언트에서 요청을 보낼 때 Session ID를 같이 보내면 현재 요청을 보내는 사용자가 누구인지 서버에서 알 수 있다. (요청마다 매번 아이디와 비밀번호를 물어볼 필요가 없음)
  4. Session ID는 데이터베이스에 저장되기 때문에 요청이 있을 때마다 데이터 베이스를 확인해야 한다.
  5. 서버에서 데이터가 저장되기 때문에 클라이언트에 사용자 정보가 노출될 위험이 없다.
  6. 데이터 베이스에 Session을 저장해야하기 때문에 Horizontal Scaling이 어렵다.

:::tip Horizontal Scaling? 서버에서 부하를 분산하기 위해서 서버를 수평적으로 확장하는 것을 뜻한다. :::

Token

유저의 정보를 Base 64로 인코딩된 String 값에 저장하는 도구를 뜻한다.

Token의 특징

  1. Tokend은 Header, Payload, Signature로 구성되어 있으며 Base 64로 인코딩 되어 있다.
  2. Token은 서버에서 생성되며 클라이언트에서 저장된다. (Session이랑 동일)
  3. 클라이언트에서 요청을 보낼 때 Token ID를 같이 보내면 현재 요청을 보내는 사용자가 누구인지 서버에서 알 수 있다. (요청마다 매번 아이디와 비밀번호를 물어볼 필요 없음) (Session이랑 동일)
  4. Token은 데이터베이스에 저장되지 않고 Signature 값을 이용해서 검증할 수 있다. 그래서 검증할 때마다 데이터베이스를 매번 들여다 볼 필요가 없다.
  5. 정보가 모두 토큰에 담겨있고 클라이언트에서 토큰을 저장하기 때문에 정보 유출의 위험이 있다.
  6. 데이터베이스가 필요없기 때문에 Horizontal Scaling이 쉽다.

Session Vs Token 비교

비교 요소SessionToken
유저 정보 저장 위치서버클라이언트
클라이언트에서 서버로 보내는 정보는?쿠키토큰
유저 정보를 가져올 때 데이터베이스를 확인해야 하는가?OX
클라이언트에서 인증 정보를 읽을 수 있는가?불가능가능
Horizontal Scaling이 쉬운가?어려움쉬움

JWT란?

  • Json Web Tokeno의 약자로 세션과 토큰을 합친 것이다.
  • Header, Payload, Signature로 구성되어 있으며 Base 64로 인코딩 되어 있다.
  • Header는 토큰의 종류와 암호화 알고리즘 등 토큰에 대한 정보가 들어있다.
  • Payload는 발행일, 만료일, 사용자 ID 등 사용작 검증에 필요한 정보가 들어있다.
  • SignatureBase64 인코딩된 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

Request 요청 Commit

에러 처리

401 Error

custom_interceptor.dart

Reference

Error 처리 Commit (opens in a new tab)