Powrót do strony głównej

Aktualizacja JWT w Dio: Podejście Interceptor

Artykuł omawia mechanizmy aktualizacji tokenów JWT w Dio: reaktywny Interceptor z Completer, proaktywny QueryInterceptor po exp. Porównanie schematów Basic/Bearer, architektura dual-token, przykłady kodu dla production.

Autoaktualizacja tokenów Dio: od teorii do kodu
Advertisement 728x90

Automatyczne odświeżanie tokenów JWT w Dio: Interceptor i QueryInterceptor

Serwery weryfikują autoryzację poprzez nagłówek Authorization w formacie <schemat-autoryzacji> <parametry-autoryzacji>. Middleware przetwarza ten nagłówek dla wszystkich chronionych endpointów. W przypadku braku lub nieprawidłowości danych zwracany jest błąd 401 Unauthorized lub 403 Forbidden.

Główne schematy:

  • Basic: Login i hasło zakodowane w Base64 (Authorization: Basic bG9naW46cGFzc3dvcmQ=). Niska bezpieczeństwo ze względu na łatwość dekodowania.
  • Bearer: Token JWT (Authorization: Bearer <Token>). Obsługuje czas ważności, wymaga odświeżania.

JWT składa się z Header (algorytm), Payload (dane użytkownika, exp), Signature (sekret serwera). Format: {Header}.{Payload}.{Signature} w Base64.

Google AdInline article slot

Struktura JWT i odświeżanie

Payload zawiera exp (czas wygaśnięcia). Przy błędzie 401 klienci żądają odświeżenia poprzez chroniony endpoint bez middleware.

Systemy dual-token:

  • Access Token: Krótki czas ważności (minuty), do zapytań API.
  • Refresh Token: Długi czas ważności, do generowania nowego Access Token.

Strategie obsługi wygasłych tokenów

Wylogowanie (najprostsze podejście)

Przy błędzie 401 — wylogowanie. Implementacja trywialna, ale niewygodna dla użytkowników.

Google AdInline article slot

Zalety:

  • Minimalny kod.

Wady:

  • Częste ponowne logowania.
  • Niekompatybilne z dual-token.

Odświeżanie po błędzie (Interceptor)

Realizowane poprzez Interceptor w Dio. Dodaje token w onRequest, obsługuje błąd 401 w onError.

Google AdInline article slot
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);
  }
}

Podłączenie:

final dio = Dio()..interceptors.add(TokenInterceptor(TokenStorage()));

W onError dla błędu 401:

  • Sprawdzamy flagę _isRefreshing.
  • Jeśli nie — uruchamiamy odświeżanie poprzez osobny Dio.
  • Kolejka zapytań czeka poprzez 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;
  }
}

Pełna logika onError synchronizuje równoległe zapytania, retry z nowym tokenem.

Zalety:

  • Działa z dual-token.
  • Bez zewnętrznych bibliotek.

Wady:

  • Fala obciążenia serwera przy masowym retry.
  • Opóźnienie odpowiedzi (błąd + odświeżanie + retry).

Proaktywne odświeżanie (QueryInterceptor)

Wykorzystuje exp z JWT do odświeżania przed wygaśnięciem. QueryInterceptor zapewnia sekwencyjne przetwarzanie zapytań.

Parsowanie JWT dla wyodrębnienia exp:

  • Zdekodować Payload z Base64.
  • Sparsować JSON, uzyskać timestamp.

Zaleta: brak blokujących błędów 401. Wada: sztywna kolejka, równoległe zapytania są blokowane.

Co jest ważne

  • Używaj Interceptor do reaktywnego odświeżania z Completer do synchronizacji.
  • QueryInterceptor nadaje się do proaktywnego odświeżania na podstawie exp.
  • Przechowuj tokeny w izolowanym storage, używaj osobnego Dio do odświeżania.
  • Obsługuj race conditions przy wielu błędach 401.
  • Dual-token zwiększa bezpieczeństwo: krótki access + refresh.

— Editorial Team

Advertisement 728x90

Czytaj dalej