Dio에서 JWT 토큰 자동 갱신: 인터셉터와 쿼리 인터셉터 활용
서버는 보호된 엔드포인트에 대해 Authorization 헤더를 통해 인증을 검증합니다. 이 헤더는 <인증-스킴> <인증-매개변수> 형식으로 구성되며, 미들웨어가 처리합니다. 데이터가 누락되거나 유효하지 않으면 401 Unauthorized 또는 403 Forbidden을 반환합니다.
주요 스킴:
- Basic: Base64로 인코딩된 로그인:비밀번호 (
Authorization: Basic bG9naW46cGFzc3dvcmQ=). 쉽게 디코딩 가능해 보안 수준이 낮습니다. - Bearer: JWT 토큰 (
Authorization: Bearer <토큰>). 만료 기능을 지원하며, 갱신이 필요합니다.
JWT는 헤더(알고리즘), 페이로드(사용자 데이터, exp), 서명(서버 비밀)으로 구성됩니다. 형식: Base64로 인코딩된 {헤더}.{페이로드}.{서명}.
JWT 구조와 갱신
페이로드에는 exp(만료 시간)가 포함됩니다. 401 오류 발생 시, 클라이언트는 미들웨어 없이 보호된 엔드포인트를 통해 갱신을 요청합니다.
이중 토큰 시스템:
- 액세스 토큰: 짧은 수명(분 단위), API 요청에 사용.
- 리프레시 토큰: 긴 수명, 새로운 액세스 토큰 생성에 사용.
만료된 토큰 처리 전략
로그아웃 (가장 간단한 접근법)
401 오류 시 — 로그아웃. 구현은 간단하지만 사용자에게 불편합니다.
장점:
- 최소한의 코드.
단점:
- 빈번한 재로그인.
- 이중 토큰과 호환되지 않음.
오류 시 갱신 (인터셉터)
Dio의 Interceptor를 통해 구현됩니다. onRequest에서 토큰을 추가하고, onError에서 401을 처리합니다.
class TokenInterceptor extends Interceptor {
final TokenStorage _storage;
TokenInterceptor(this._storage);
@override
Future<void> onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
final token = await _storage.getToken();
if (token != null) {
options.headers['Authorization'] = 'Bearer $token';
}
handler.next(options);
}
}
설정:
final dio = Dio()..interceptors.add(TokenInterceptor(TokenStorage()));
onError에서 401 처리:
_isRefreshing플래그 확인.- 갱신 중이 아니면 — 별도의 Dio를 통해 갱신 시작.
- 대기 중인 요청은
Completer<void> _refreshCompleter를 통해 대기.
Future<String?> _updateToken() async {
final oldToken = await _storage.getToken();
try {
final dio = Dio();
final response = await dio.get('/auth/refresh/', headers: {'Authorization': 'Bearer $oldToken'});
final newToken = (response.data as Map<String, dynamic>)['token'];
await _storage.setNewToken(newToken);
return newToken;
} catch (e) {
await _storage.clearToken();
return null;
}
}
전체 onError 로직은 병렬 요청을 동기화하고, 새 토큰으로 재시도합니다.
장점:
- 이중 토큰과 작동.
- 외부 라이브러리 불필요.
단점:
- 대량 재시도 시 서버에 부하 발생.
- 응답 지연(오류 + 갱신 + 재시도).
사전 갱신 (쿼리 인터셉터)
JWT의 exp를 사용해 만료 전에 갱신합니다. QueryInterceptor는 순차적 요청 처리를 보장합니다.
JWT를 파싱하여 exp 추출:
- Base64 페이로드 디코딩.
- JSON 파싱, 타임스탬프 획득.
장점: 401 오류 차단 없음. 단점: 엄격한 큐, 병렬 요청이 차단됨.
핵심 요약
Interceptor를 사용해Completer로 동기화된 반응적 갱신 구현.QueryInterceptor는exp기반 사전 갱신에 적합.- 토큰을 격리된 저장소에 보관, 갱신용 별도 Dio 사용.
- 다중 401 발생 시 경쟁 조건 처리.
- 이중 토큰으로 보안 강화: 짧은 액세스 + 리프레시.
— Editorial Team
아직 댓글이 없습니다.