Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Процедура обработки просроченного токена в Frontend-приложениях
Когда токен аутентификации (например, JWT — JSON Web Token) просрочился, фронтенд-приложение должно реализовать четкую стратегию восстановления работоспособности пользовательского сеанса. Это критически важно для обеспечения непрерывного взаимодействия пользователя с приложением без необходимости повторного ввода логина и пароля. Вот подробный план действий.
1. Механизм обнаружения просроченного токена
Чаще всего просрочка обнаруживается при попытке выполнить HTTP-запрос к защищенному API-эндпоинту. Сервер отвечает статусом 401 Unauthorized или 403 Forbidden. Клиентский код должен анализировать такие ответы.
// Пример обработки ответа в HTTP-клиенте (например, axios)
axios.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 401) {
// Запускаем процедуру обновления токена
return handleTokenRefresh(error);
}
return Promise.reject(error);
}
);
2. Стратегия обновления токена (Refresh Token Flow)
Наиболее распространенный и безопасный подход — использование пары Access Token (короткоживущий, например, 15 минут) и Refresh Token (долгоживущий, например, 7 дней). При получении ошибки 401 фронтенд отправляет Refresh Token на специальный эндпоинт для получения нового Access Token.
Последовательность действий:
- Получаем ошибку
401на запрос с текущимAccess Token. - Проверяем наличие
Refresh Tokenв безопасном хранилище (например, httpOnly cookie или secure client storage). - Отправляем запрос на эндпоинт
/auth/refreshсRefresh Token. - Получаем новый
Access Tokenи, возможно, новыйRefresh Token. - Обновляем токены в хранилище клиента.
- Повторяем оригинальный запрос, который вызвал ошибку, с новым
Access Token.
// Пример функции обновления токена
async function refreshAccessToken() {
const refreshToken = localStorage.getItem('refreshToken'); // Или из cookie
try {
const response = await axios.post('/api/auth/refresh', {
refreshToken
});
const { accessToken, refreshToken: newRefreshToken } = response.data;
// Обновляем токены в хранилище
localStorage.setItem('accessToken', accessToken);
if (newRefreshToken) {
localStorage.setItem('refreshToken', newRefreshToken);
}
return accessToken;
} catch (refreshError) {
// Если refresh тоже не удался — полная сессия умерла
logoutUser();
throw new Error('Session expired');
}
}
3. Повтор запроса после успешного обновления
После успешного обновления необходимо повторно выполнить исходный запрос пользователя. Это важно для непрерывности UX.
async function handleTokenRefresh(originalError) {
try {
const newAccessToken = await refreshAccessToken();
// Повтор оригинального запроса с новым токеном
originalError.config.headers.Authorization = `Bearer ${newAccessToken}`;
return axios(originalError.config);
} catch (error) {
// Если обновление не удалось — направляем пользователя на логин
redirectToLogin();
return Promise.reject(error);
}
}
4. Обработка неудачного обновления токена
Если Refresh Token также просрочен, отозван или недействителен, сервер вернет ошибку (обычно тоже 401 или 400). В этом случае фронтенд должен:
- Очистить все токены из хранилища клиента.
- Перенаправить пользователя на страницу логина.
- Показать соответствующее сообщение (например, «Сессия завершена, пожалуйста, войдите снова»).
5. Превентивные стратегии (Proactive Refresh)
Чтобы минимизировать случаи просрочки во время активных операций пользователя, можно реализовать превентивное обновление токена перед его фактическим истечением. Например, запускать обновление, когда осталось 1-2 минуты до expiry времени.
// Пример: проверка времени жизни токена перед запросом
function isTokenExpired(accessToken) {
const payload = JSON.parse(atob(accessToken.split('.')[1]));
const expiryTime = payload.exp * 1000; // Конвертируем из UNIX timestamp
return Date.now() >= expiryTime - 60000; // Проверяем, если осталось меньше минуты
}
// Можно использовать в интерцепторе запросов
axios.interceptors.request.use(
(config) => {
const accessToken = localStorage.getItem('accessToken');
if (isTokenExpired(accessToken)) {
// Превентивно обновляем токен перед отправкой запроса
return refreshAccessToken().then(newToken => {
config.headers.Authorization = `Bearer ${newToken}`;
return config;
});
}
return config;
}
);
6. Архитектурные решения и безопасность
- Хранение токенов:
Access Tokenможно хранить в памяти илиlocalStorageдля SPA, ноRefresh Tokenдолжен быть максимально защищен (httpOnly cookie идеально). - Обработка параллельных запросов: Если несколько запросов одновременно получают
401, нужно предотвратить запуск множества одновременных refresh-запросов. Реализуйте механизм блокировки и очереди. - Информирование пользователя: При перенаправлении на логин из-за просрочки можно сохранить состояние интерфейса или текущий URL для возврата после успешного повторного входа.
Ключевой принцип: Просроченный токен — это не ошибка, а нормальный жизненный цикл сессии. Фронтенд должен обрабатывать это автоматически и максимально незаметно для пользователя, обеспечивая баланс между безопасностью и удобством.