0Pricing
C# Academy · Урок

Токены обновления и срок действия

Реализуйте безопасное обновление токенов.

«Токены обновления и срок действия» — бесплатный урок 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 — локальная установка не требуется.

Все уроки этого курса

  1. Структура JWT и утверждения
  2. Настройка аутентификации JWT Bearer
  3. Выдача токенов
  4. Токены обновления и срок действия
← Назад к C# Academy