前言:给 API 装个“门禁卡” 认证你是谁查验身份证授权你能干什么查看权限列表在前后端分离的架构中JWT (JSON Web Token) 是目前最流行的认证方案。它就像一张“电子门禁卡”。用户登录成功后服务器发给他一张卡Token以后每次请求都要带着这张卡服务器只需验证卡的真伪而不需要每次都去查数据库。二、JWT 到底是什么刚子不喜欢背书你只需要理解三个核心点一个 JWT 就是一个很长的字符串长得像这样 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IuWkp…它由三部分组成用 . 分隔Header头说明这是什么卡用什么加密算法。Payload载荷重点。里面存着用户信息如用户ID、用户名、角色。注意这里的数据只是 Base64 编码不要存密码Signature签名核心安全层。服务器用只有自己知道的密钥对前两部分进行签名。黑客如果篡改了 Payload签名就对不上了服务器会直接拒绝。JWT (JSON Web Token) 的三部分结构示意图三、实战准备安装 NuGet 包在项目中安装以下 NuGet 包dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer这会引入处理 JWT 验证的核心中间件。四、第一步打造“发卡处”用户登录时我们需要核实账号密码然后生成 Token 发给他。为了演示方便我们假设有一个模拟的用户库。4.1 定义配置模型和模拟用户在 Program.cs 顶部定义模型// 定义用户模型public class User{public string Username { get; set; }public string Password { get; set; } // 实际项目中应存储哈希值public string Role { get; set; } // 角色Admin, User}// 模拟数据库用户public static class UserStore{public static List Users new List{new User { Username “admin”, Password “123456”, Role “Admin” },new User { Username “gangzi”, Password “123456”, Role “User” }};}4.2 编写登录接口这个接口负责“发卡”。using System.IdentityModel.Tokens.Jwt;using System.Security.Claims;using System.Text;using Microsoft.IdentityModel.Tokens;// … builder 配置 …app.MapPost(“/login”, (User login) {// 1. 验证账号密码var user UserStore.Users.FirstOrDefault(u u.Username login.Username u.Password login.Password);if (user null){return Results.Unauthorized(); // 401 未授权}// 2. 创建 Claims声明 - 也就是 Payload 里要存的数据 var claims new ListClaim { new Claim(ClaimTypes.Name, user.Username), new Claim(ClaimTypes.Role, user.Role), // 存入角色用于授权 new Claim(MyCustomClaim, SomeData) // 也可以存自定义数据 }; // 3. 生成签名密钥实际项目中应从 appsettings.json 读取 // 密钥至少要 16 个字符 var secretKey This_Is_A_Very_Secret_Key_For_JWT_2026!; var key new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey)); var creds new SigningCredentials(key, SecurityAlgorithms.HmacSha256); // 4. 生成 Token var token new JwtSecurityToken( issuer: MyTodoApp, // 签发者 audience: MyTodoAppUsers, // 接收者 claims: claims, expires: DateTime.Now.AddHours(1), // 过期时间1小时 signingCredentials: creds ); var tokenString new JwtSecurityTokenHandler().WriteToken(token); return Results.Ok(new { Token tokenString });});刚子敲黑板 这里的 secretKey 是服务器的“底牌”。绝对不能泄露如果黑客拿到了这个 Key他就能伪造任意用户的 Token。在生产环境中一定要放在 appsettings.json 或环境变量里并且长度要足够长。五、第二步配置“安检门”有了发卡的逻辑还需要配置中间件让系统自动验证每个请求带来的 Token。5.1 注册认证与授权服务在 Program.cs 的 builder.Services 部分添加// 注册认证服务builder.Services.AddAuthentication(options {options.DefaultAuthenticateScheme JwtBearerDefaults.AuthenticationScheme;options.DefaultChallengeScheme JwtBearerDefaults.AuthenticationScheme;}).AddJwtBearer(options {// 配置 Token 验证参数options.TokenValidationParameters new TokenValidationParameters{ValidateIssuer true,ValidateAudience true,ValidateLifetime true,ValidateIssuerSigningKey true,ValidIssuer MyTodoApp, ValidAudience MyTodoAppUsers, IssuerSigningKey new SymmetricSecurityKey(Encoding.UTF8.GetBytes(This_Is_A_Very_Secret_Key_For_JWT_2026!)) };});// 注册授权服务builder.Services.AddAuthorization();5.2 启用中间件在 app.Build() 之后确保顺序正确UseAuthentication 必须在 UseAuthorization 之前。var app builder.Build();app.UseAuthentication(); // 开启认证识别身份app.UseAuthorization(); // 开启授权检查权限// … 其他中间件 …六、第三步保护你的 API现在安检门装好了我们给之前的 Todo 接口加上“锁”。6.1 普通保护登录才能访问在 Minimal API 中使用 RequireAuthorization() 扩展方法。// 只有带了有效 Token 才能访问app.MapGet(“/todos”, async (AppDbContext db) {return await db.Todos.ToListAsync();}).RequireAuthorization();6.2 角色保护管理员才能删除假设删除操作只有 “Admin” 角色才能执行。app.MapDelete(“/todos/{id}”, async (int id, AppDbContext db) {// … 删除逻辑 …return Results.NoContent();}).RequireAuthorization(“Admin”); // 这是错误的写法修正Minimal API 的角色授权需要配合策略或者简写为// 正确写法定义一个策略或者使用 Claimsapp.MapDelete(“/todos/{id}”, async (int id, AppDbContext db) {// … 删除逻辑 …}).RequireAuthorization(policy policy.RequireRole(“Admin”));七、实战测试完整流程演示让我们用 Postman 或 Swagger 演示整个流程。场景一未登录直接访问访问 GET /todos。结果401 Unauthorized。系统拒绝访问。未登录状态访问/todos 返回401 Unauthorized