Я столкнулся с подобной проблемой и попытался решить ее, используя следующий подход.
Я использую flutter-redux
для управления состоянием на стороне клиента.
- Получите токен jwt после входа в систему
- Расшифруйте токен jwt на стороне клиента в ответ на запрос от сервера.
- Содержит тайм-аут - время истечения.
- Создание промежуточного промежуточного программного обеспечения на стороне клиента, скажем,
_createRefreshTokenMiddleware
. - Каждый запрос от клиента должен проходить через это промежуточное программное обеспечение перед отправкой на сервер.
- В этом промежуточном программном обеспечении при каждом запросе к серверу проверяется время ожидания токена, если токен истек, удерживайте запрос, отправьте запрос на сервер, чтобы обновить токен, дождитесь получения нового токена, используйте этот новый токен, чтобы отправить запрос на сервер.
- Все остальные запросы, для которых истекает токен, будут ожидать обычного обещания.Допустим, скажем
refreshTokenPromise
, чтобы получить refreshToken будет решен в первую очередь.Таким образом, вам не нужно отправлять несколько запросов refreshToken. - Если токен все еще действителен, разрешите выполнение запросов.
См. Приведенный ниже пример -
Ваше промежуточное ПО:
Middleware<AppState> _createRefreshTokenMiddleware() {
return (Store store, action, NextDispatcher next) async {
AppState appState = store.state;
AuthState auth = appState.auth;
if (isTokenExpired(auth)) {
if (auth.refreshTokenPromise == null) {
refreshToken(store).then((res) => next(action));
} else {
auth.refreshTokenPromise.then((res) => next(action));
}
}
next(action);
};
}
Все запросы, для которых истек срок действия токена, будут ожидать refreshTokenPromise
, и как только это будет решено, все ожидающие запросыбудет установлен новый обновленный токен в заголовке запроса (например).
Проверка истечения срока действия токена:
bool isTokenExpired(AuthState auth) {
int bufferSeconds = 10;
if(auth != null && auth.authTokens != null && auth.authTokens.tokenExpiryTime != null) {
var currentTime = DateTime.now();
Duration durationRemaining = auth.authTokens.tokenExpiryTime.difference(currentTime);
return (durationRemaining.inSeconds - bufferSeconds) <= 0 ? true : false;
}
return false;
}
Вы отправляете запрос на обновление токена за 10 секунд до негосрок действия истек.
AuthState Модель:
@ неизменяемый класс AuthState {
// properties
final bool isAuthenticated;
final bool isAuthenticating;
final AuthTokens authTokens;
final String error;
final Future<dynamic> refreshTokenPromise;
// constructor with default
AuthState({
this.isAuthenticated = false,
this.isAuthenticating = false,
this.authTokens,
this.error,
this.refreshTokenPromise,
});
}
Ваше состояние авторизациимодель может быть такой же, как и выше.
AuthToken:
@immutable
class AuthTokens {
// properties
final String accessToken;
final String refreshToken;
final DateTime tokenExpiryTime;
// constructor with default
AuthTokens({
this.accessToken,
this.refreshToken,
this.tokenExpiryTime,
});
}
Хотя я дал здесь решение на основе редуксов, но такую же стратегию можно применять и в других местах.Надеюсь, это поможет.