Ответ
JSON Web Token (JWT) — это компактный, URL-безопасный способ представления claims (утверждений), которые передаются между двумя сторонами. Он состоит из трёх частей (Header.Payload.Signature), подписанных цифровой подписью.
Преимущества:
- Stateless (без состояния): Серверу не нужно хранить сессию пользователя в памяти или БД. Вся необходимая информация содержится в самом токене, что упрощает масштабирование.
- Самостоятельность (Self-contained): Токен может содержать основные claims (например,
userId,roles), что уменьшает количество запросов к БД для проверки прав. - Универсальность: Легко используется в различных клиентах (веб, мобильные приложения, микросервисы) и протоколах (REST/GraphQL).
- Цифровая подпись: Гарантирует целостность данных. Изменение payload или header инвалидирует подпись.
Недостатки и риски:
- Немедленный отзыв (Revocation): Основная проблема. Токен валиден до истечения срока его жизни (
exp). Для принудительного отзыва приходится использовать чёрные списки токенов (что нарушает stateless-принцип) или очень короткие сроки жизни с обновлением через refresh-токены. - Размер: JWT больше, чем обычный идентификатор сессии. При каждом запросе он передаётся в заголовке
Authorization, увеличивая трафик. - Хранение на клиенте: Уязвим к атакам XSS, если хранится в
localStorage. Безопаснее хранить вHttpOnlycookie, но это усложняет использование для нативных мобильных приложений. - Не шифрование по умолчанию: JWT только подписан (JWS), но не зашифрован (JWE). Конфиденциальные данные в payload видны всем, кто получит токен (используйте JWE или не кладите такие данные).
Пример создания и валидации в .NET:
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
// Создание токена
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your_super_secret_key"));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim("sub", "user123"),
new Claim("role", "Admin")
}),
Expires = DateTime.UtcNow.AddHours(1),
SigningCredentials = credentials,
Issuer = "your-api"
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
var jwtString = tokenHandler.WriteToken(token);
// Валидация токена в Middleware (Program.cs)
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = "your-api",
ValidateAudience = false, // Или установите свою аудиторию
ValidateLifetime = true,
IssuerSigningKey = securityKey
};
});
Когда использовать: JWT идеален для stateless API, микросервисной архитектуры и single-page applications. Для традиционных веб-приложений с серверным рендерингом часто предпочтительнее классические cookie-сессии.