JWT 是一种开放标准(RFC 7519),用于在各方之间安全传输信息。其核心优势在于:
// 示例 JWT 结构(Base64Url 编码)
xxxxx.yyyyy.zzzzz
描述签名算法和 Token 类型:
{
"alg": "HS256", // 签名算法(如 HMAC SHA256)
"typ": "JWT" // Token 类型
}
存储声明(Claims),包含用户信息、过期时间等:
{
"sub": "1234567890", // 主题(用户ID)
"name": "John Doe", // 用户名
"admin": true, // 角色权限
"exp": 1516239022 // 过期时间(Unix 时间戳)
}
通过 Header 和 Payload 生成的签名,用于验证完整性:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secretKey
)
# 使用 NuGet 安装 JWT 相关包
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add package System.IdentityModel.Tokens.Jwt
以下代码演示如何在用户登录后生成 Token:
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;
public class JwtHelper
{
// 密钥(需确保安全性,建议从配置文件读取)
private static readonly string SecretKey = "YOUR_256_BIT_SECRET_KEY";
private static readonly SymmetricSecurityKey Key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecretKey));
private static readonly SigningCredentials Credentials = new SigningCredentials(Key, SecurityAlgorithms.HmacSha256);
///
/// 生成 JWT Token
///
/// 用户ID
/// 用户名
/// 用户角色
/// JWT 字符串
public static string GenerateToken(string userId, string username, string role)
{
// 定义 Claims(声明)
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, userId), // 用户ID
new Claim(JwtRegisteredClaimNames.UniqueName, username), // 用户名
new Claim("role", role), // 自定义角色
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), // 唯一标识
new Claim(JwtRegisteredClaimNames.Iat,
new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds().ToString(),
ClaimValueTypes.Integer64) // 签发时间
};
// 创建 Token
var token = new JwtSecurityToken(
issuer: "MyWebAPI", // 颁发者
audience: "MyClientApp", // 受众
claims: claims,
expires: DateTime.Now.AddHours(1), // 过期时间
signingCredentials: Credentials // 签名凭证
);
// 返回 Token 字符串
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
在 Web API 中配置 JWT 验证中间件,确保请求携带合法 Token:
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
var builder = WebApplication.CreateBuilder(args);
// 从配置文件读取 JWT 参数
var jwtSettings = builder.Configuration.GetSection("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 = jwtSettings["Issuer"], // 颁发者
ValidAudience = jwtSettings["Audience"], // 受众
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(jwtSettings["SecretKey"])) // 密钥
};
// 处理 Token 刷新(可选)
options.Events = new JwtBearerEvents
{
OnTokenValidated = context =>
{
// 自定义验证逻辑(如检查用户是否被禁用)
return Task.CompletedTask;
}
};
});
// 启用身份验证和授权
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.Run();
{
"Jwt": {
"SecretKey": "YOUR_256_BIT_SECRET_KEY",
"Issuer": "MyWebAPI",
"Audience": "MyClientApp"
}
}
通过添加自定义 Claims,可以扩展 Token 的功能:
var claims = new[]
{
new Claim("department", "Engineering"), // 自定义部门
new Claim("organization", "Acme Corp") // 自定义组织
};
在验证时,可以通过 User.FindFirst("department")
获取自定义 Claims。
为避免频繁登录,可引入刷新 Token:
// 生成刷新 Token(通常存储在数据库)
var refreshToken = new RefreshToken
{
UserId = userId,
Token = Guid.NewGuid().ToString(),
ExpiryTime = DateTime.Now.AddDays(7)
};
// 返回刷新 Token 给客户端
return new
{
AccessToken = accessToken,
RefreshToken = refreshToken.Token
};
在 Startup.cs
中配置 CORS 策略:
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAll", policy =>
{
policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
// 在中间件中启用 CORS
app.UseCors("AllowAll");
确保 Token 在传输过程中加密:
app.UseHttpsRedirection(); // 强制 HTTPS
避免长期有效的 Token:
expires: DateTime.Now.AddMinutes(30) // 设置较短的过期时间
不要在 JWT 中存储敏感信息(如密码、密钥)。
原因:密钥不匹配或 Token 被篡改
解决方案:
原因:Token 过期
解决方案:
原因:Token 的受众(Audience)与服务端配置不匹配
解决方案:
var builder = WebApplication.CreateBuilder(args);
// 从配置文件读取 JWT 参数
var jwtSettings = builder.Configuration.GetSection("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 = jwtSettings["Issuer"],
ValidAudience = jwtSettings["Audience"],
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(jwtSettings["SecretKey"]))
};
});
builder.Services.AddAuthorization(); // 添加授权服务
var app = builder.Build();
// 中间件顺序至关重要!
app.UseRouting();
app.UseAuthentication(); // 必须在 UseAuthorization 之前
app.UseAuthorization();
// 保护 API 端点
app.MapControllers().RequireAuthorization();
app.Run();
JWT 通常与 OAuth 2.0 结合使用,实现第三方登录:
builder.Services.AddAuthentication()
.AddOAuth2Introspection(options =>
{
options.Authority = "https://your-oauth-server.com";
options.ClientId = "your-client-id";
options.ClientSecret = "your-client-secret";
});
结合 AI 技术(如行为分析、异常检测),进一步提升身份认证的安全性。
通过本文的实战演练,你已掌握:
✅ JWT 的生成与验证全流程
✅ .NET 中的 JWT 高级配置技巧
✅ 生产级安全实践方案
✅ 常见错误的诊断与修复