Токены обновления и срок действия
Реализуйте безопасное обновление токенов.
«Токены обновления и срок действия» — бесплатный урок C# Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C# Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C# Academy содержит 4 уроков всего.
Проблема истечения срока действия
Токены доступа с коротким сроком действия безопасны, но неудобны: заставлять пользователей входить в систему каждые 15 минут — плохое решение с точки зрения пользовательского опыта.
Решение — токен обновления: отдельный учётный объект с более длительным сроком действия, используемый для получения новых токенов доступа без повторного ввода пароля.
// access token: 15 minutes
// refresh token: 7-30 daysЧто такое токен обновления
Токен обновления обычно представляет собой непрозрачную случайную строку, а не JWT. Поскольку он действует долго, его необходимо хранить на сервере, чтобы иметь возможность отозвать его.
Создавайте его с помощью криптографически безопасного генератора случайных чисел.
public static string GenerateRefreshToken()
{
var bytes = new byte[64];
using var rng = RandomNumberGenerator.Create();
rng.GetBytes(bytes);
return Convert.ToBase64String(bytes);
}Хранение токенов обновления
Сохраняйте каждый токен обновления вместе с его владельцем, сроком действия и флагом отзыва. Это позволяет сделать токен недействительным при выходе из системы или краже.
public class RefreshToken
{
public int Id { get; set; }
public string Token { get; set; } = default!;
public int UserId { get; set; }
public DateTime ExpiresAt { get; set; }
public bool IsRevoked { get; set; }
}Выдача обоих токенов при входе
После успешного входа верните короткоживущий токен доступа и новый токен обновления. Сохраните токен обновления в базе данных.
var access = tokenService.CreateAccessToken(user);
var refresh = new RefreshToken
{
Token = TokenService.GenerateRefreshToken(),
UserId = user.Id,
ExpiresAt = DateTime.UtcNow.AddDays(7)
};
db.RefreshTokens.Add(refresh);
await db.SaveChangesAsync();
return Results.Ok(new { access, refresh = refresh.Token });Конечная точка обновления
Специализированная конечная точка /refresh принимает токен обновления и, если он действителен, выдаёт совершенно новый токен доступа.
app.MapPost("/refresh", async (RefreshDto dto, AppDb db, TokenService tokens) =>
{
var stored = await db.RefreshTokens
.SingleOrDefaultAsync(r => r.Token == dto.RefreshToken);
if (stored is null || stored.IsRevoked ||
stored.ExpiresAt < DateTime.UtcNow)
return Results.Unauthorized();
var user = await db.Users.FindAsync(stored.UserId);
var access = tokens.CreateAccessToken(user!);
return Results.Ok(new { access });
});Ротация токенов обновления
Ротация повышает безопасность этого процесса: каждый раз при использовании токена обновления отзывайте его и выдавайте новый. Украденный уже использованный токен после этого становится бесполезным.
stored.IsRevoked = true; // burn the old one
var next = new RefreshToken
{
Token = TokenService.GenerateRefreshToken(),
UserId = stored.UserId,
ExpiresAt = DateTime.UtcNow.AddDays(7)
};
db.RefreshTokens.Add(next);
await db.SaveChangesAsync();Обнаружение повторного использования токена
Ротация позволяет обнаружить кражу: если уже отозванный токен предъявлен снова, расценивайте это как компрометацию и отзывайте всё семейство токенов пользователя.
if (stored.IsRevoked)
{
// This token was already used - likely stolen.
await RevokeAllUserTokens(stored.UserId, db);
return Results.Unauthorized();
}Выход из системы и отзыв токенов
При выходе из системы просто отзовите текущий токен обновления. Токен доступа самостоятельно истечёт в течение нескольких минут.
app.MapPost("/logout", async (RefreshDto dto, AppDb db) =>
{
var stored = await db.RefreshTokens
.SingleOrDefaultAsync(r => r.Token == dto.RefreshToken);
if (stored is not null) stored.IsRevoked = true;
await db.SaveChangesAsync();
return Results.Ok();
}).RequireAuthorization();Где хранить токены на клиенте
Для браузеров наиболее безопасный вариант — хранить токен обновления в cookie с атрибутом HttpOnly и флагом защиты, чтобы JavaScript не мог его прочитать, что снижает риск кражи через XSS.
Короткоживущий токен доступа можно хранить в памяти.
Response.Cookies.Append("refresh", refresh.Token, new CookieOptions
{
HttpOnly = true,
Secure = true,
SameSite = SameSiteMode.Strict,
Expires = refresh.ExpiresAt
});Удаление просроченных токенов
Токены обновления накапливаются. Запускайте периодическую фоновую задачу (например, размещённую службу), чтобы удалять просроченные или отозванные строки.
await db.RefreshTokens
.Where(r => r.ExpiresAt < DateTime.UtcNow || r.IsRevoked)
.ExecuteDeleteAsync();Выбор сроков действия
Соблюдайте баланс между безопасностью и удобством:
- Токен доступа: 5–15 минут — ограничивает период использования украденного токена.
- Токен обновления: от нескольких часов до нескольких недель, в зависимости от чувствительности данных.
- Используйте ротацию для токенов со сроком действия более суток.
AccessTokenLifetime = TimeSpan.FromMinutes(15);
RefreshTokenLifetime = TimeSpan.FromDays(7);Быстрая проверка
Проверьте своё понимание процесса обновления.
Повторение
Вы реализовали процесс обновления токенов:
- Выдавайте короткоживущий токен доступа и длинный непрозрачный токен обновления, хранящийся на сервере.
- Конечная точка
/refreshобменивает действительный токен обновления на новый токен доступа. - Ротация и обнаружение повторного использования повышают защиту от кражи.
- Храните токены обновления в cookie HttpOnly и удаляйте просроченные строки.
На этом курс аутентификации JWT завершён.
Часто задаваемые вопросы
Урок «Токены обновления и срок действия» бесплатный?
Да — полный текст урока «Токены обновления и срок действия» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C# Academy, подпишись на CoddyKit PRO. Курс C# Academy содержит 4 уроков всего.
Чему я научусь в уроке «Токены обновления и срок действия»?
Реализуйте безопасное обновление токенов. Ты практикуешь C# Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C# Academy?
Предыдущий опыт не требуется. C# Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Токены обновления и срок действия»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C# Academy?
Да. Каждый урок C# Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Структура JWT и утверждения
- Настройка аутентификации JWT Bearer
- Выдача токенов
- Токены обновления и срок действия