JWT токены в C# (.NET): создание, проверка и валидация
JSON Web Token (JWT) — это открытый стандарт (RFC 7519) для создания токенов доступа, основанных на формате JSON. JWT широко используется в современных веб-приложениях для аутентификации и обмена информацией между клиентом и сервером. В этой статье мы подробно рассмотрим, как работать с JWT токенами в экосистеме C# (.NET), включая создание, подпись, проверку и валидацию токенов.
Основные компоненты JWT
JWT состоит из трех частей, разделенных точками:
- Header — заголовок, содержащий информацию о типе токена и алгоритме подписи
- Payload — полезная нагрузка с данными (claims)
- Signature — подпись, обеспечивающая целостность токена
Пример JWT токена: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Установка необходимых пакетов
Для работы с JWT в .NET необходимо установить пакет System.IdentityModel.Tokens.Jwt. Это можно сделать через NuGet Package Manager или с помощью .NET CLI:
dotnet add package System.IdentityModel.Tokens.Jwt
Также может потребоваться установить Microsoft.AspNetCore.Authentication.JwtBearer для интеграции с ASP.NET Core:
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
Создание JWT токена в C#
Рассмотрим полный пример создания JWT токена с использованием симметричного ключа (HMAC SHA256):
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;
public class JwtService
{
private readonly string _secretKey;
private readonly string _issuer;
private readonly string _audience;
public JwtService(string secretKey, string issuer, string audience)
{
_secretKey = secretKey;
_issuer = issuer;
_audience = audience;
}
public string GenerateToken(string userId, string userName, string role)
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_secretKey));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(ClaimTypes.NameIdentifier, userId),
new Claim(ClaimTypes.Name, userName),
new Claim(ClaimTypes.Role, role),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Iat,
new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds().ToString())
};
var token = new JwtSecurityToken(
issuer: _issuer,
audience: _audience,
claims: claims,
expires: DateTime.UtcNow.AddHours(1),
signingCredentials: credentials
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
Проверка и валидация JWT токена
Для проверки подлинности и извлечения данных из токена используется метод ValidateToken:
public ClaimsPrincipal ValidateToken(string token)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.UTF8.GetBytes(_secretKey);
try
{
var principal = tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = true,
ValidIssuer = _issuer,
ValidateAudience = true,
ValidAudience = _audience,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
}, out SecurityToken validatedToken);
return principal;
}
catch (SecurityTokenException ex)
{
// Обработка ошибок валидации
throw new UnauthorizedAccessException("Invalid token", ex);
}
}
Настройка JWT аутентификации в ASP.NET Core
Для использования JWT в веб-приложении ASP.NET Core необходимо настроить аутентификацию в Program.cs или Startup.cs:
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
// Настройка JWT аутентификации
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Audience