在前面的文章里我们的 Todo API 就像一栋没有大门的房子任何人都可以随意进出调用接口。这在企业级应用中是绝对不允许的。我们需要一套机制认证你是谁查验身份证授权你能干什么查看权限列表在前后端分离的架构中JWT (JSON Web Token)是目前最流行的认证方案。它就像一张“电子门禁卡”。用户登录成功后服务器发给他一张卡Token以后每次请求都要带着这张卡服务器只需验证卡的真伪而不需要每次都去查数据库。二、JWT 到底是什么刚子不喜欢背书你只需要理解三个核心点一个 JWT 就是一个很长的字符串长得像这样eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IuWkp...它由三部分组成用.分隔Header头说明这是什么卡用什么加密算法。Payload载荷重点。里面存着用户信息如用户ID、用户名、角色。注意这里的数据只是 Base64 编码不要存密码Signature签名核心安全层。服务器用只有自己知道的密钥对前两部分进行签名。黑客如果篡改了 Payload签名就对不上了服务器会直接拒绝。三、实战准备安装 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 ListUser Users new ListUser { 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 的角色授权需要配合策略或者简写为// 正确写法定义一个策略或者使用 Claims app.MapDelete(/todos/{id}, async (int id, AppDbContext db) { // ... 删除逻辑 ... }).RequireAuthorization(policy policy.RequireRole(Admin));七、实战测试完整流程演示让我们用 Postman 或 Swagger 演示整个流程。场景一未登录直接访问访问GET /todos。结果401 Unauthorized。系统拒绝访问。场景二登录获取 Token访问POST /loginBody 传入{username: admin, password: 123456}。结果返回一个 JSON包含 Token 字符串。场景三携带 Token 访问复制刚才的 Token。在请求头中添加Authorization: Bearer 你的Token。注意 Bearer 后有个空格再次访问GET /todos。结果200 OK成功返回数据场景四权限不足用gangzi用户登录角色是 User。携带 Token 访问DELETE /todos/1。结果403 Forbidden。虽然登录了但权限不够。八、刚子小贴士安全避坑指南HTTPS 是必须的JWT 默认不加密Token 在网络传输中如果被截获黑客就能冒充用户。唯一的防御手段就是 HTTPS 加密传输。不要存敏感信息Payload 任何人都能解码看到千万别把密码、身份证号存进去。Token 有效期设置合理的过期时间如 2 小时。为了体验通常会配合“Refresh Token”刷新令牌机制这属于进阶话题感兴趣的同学可以自行研究。配置文件管理不要把密钥硬编码在代码里请迁移到appsettings.json的Jwt:Key配置项中并使用IConfiguration读取。九、总结与下篇预告在这篇文章中我们完成了系统的安全闭环理解了 JWT 的原理Header、Payload、Signature。实现了/login接口颁发 Token。配置了中间件验证 Token。学会了RequireAuthorization和基于角色的权限控制。现在的应用已经是一个功能完备、安全可靠的系统了下一篇预告代码写完了安全也加了最后一步就是让它真正跑在服务器上。 在第八篇最终篇中刚子将带你进入容器化部署的世界。我们将编写 Dockerfile把应用打包成 Docker 镜像并在容器中运行。这标志着你从“开发模式”正式迈入“交付模式”。最后一公里我们下期见原文链接.NET 8 Web开发入门七安全门禁——JWT 身份验证与授权实战 - 码农刚子的开发笔记合集: .NET 8 现代Web开发实战指南标签: JWT, JSON Web Token, 身份验证, 授权, 接口安全, Bearer Token, .NET 8 Security免责声明本内容来自平台创作者博客园系信息发布平台仅提供信息存储空间服务。好文要顶 关注我 收藏该文 微信分享编辑码农刚子粉丝 - 61 关注 - 11加关注3« 上一篇 .NET 8 Web开发入门六Blazor 全栈开发——告别 JavaScript 焦虑» 下一篇 EF Core 8 SQL ServerContains() 突然报 关键字 WITH 附近有语法错误一篇避坑指南posted 2026-06-04 07:57 码农刚子 阅读(420) 评论(0) 收藏 举报
NET 8 Web开发入门(七):安全门禁——JWT 身份验证与授权实战
发布时间:2026/6/23 11:21:47
在前面的文章里我们的 Todo API 就像一栋没有大门的房子任何人都可以随意进出调用接口。这在企业级应用中是绝对不允许的。我们需要一套机制认证你是谁查验身份证授权你能干什么查看权限列表在前后端分离的架构中JWT (JSON Web Token)是目前最流行的认证方案。它就像一张“电子门禁卡”。用户登录成功后服务器发给他一张卡Token以后每次请求都要带着这张卡服务器只需验证卡的真伪而不需要每次都去查数据库。二、JWT 到底是什么刚子不喜欢背书你只需要理解三个核心点一个 JWT 就是一个很长的字符串长得像这样eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IuWkp...它由三部分组成用.分隔Header头说明这是什么卡用什么加密算法。Payload载荷重点。里面存着用户信息如用户ID、用户名、角色。注意这里的数据只是 Base64 编码不要存密码Signature签名核心安全层。服务器用只有自己知道的密钥对前两部分进行签名。黑客如果篡改了 Payload签名就对不上了服务器会直接拒绝。三、实战准备安装 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 ListUser Users new ListUser { 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 的角色授权需要配合策略或者简写为// 正确写法定义一个策略或者使用 Claims app.MapDelete(/todos/{id}, async (int id, AppDbContext db) { // ... 删除逻辑 ... }).RequireAuthorization(policy policy.RequireRole(Admin));七、实战测试完整流程演示让我们用 Postman 或 Swagger 演示整个流程。场景一未登录直接访问访问GET /todos。结果401 Unauthorized。系统拒绝访问。场景二登录获取 Token访问POST /loginBody 传入{username: admin, password: 123456}。结果返回一个 JSON包含 Token 字符串。场景三携带 Token 访问复制刚才的 Token。在请求头中添加Authorization: Bearer 你的Token。注意 Bearer 后有个空格再次访问GET /todos。结果200 OK成功返回数据场景四权限不足用gangzi用户登录角色是 User。携带 Token 访问DELETE /todos/1。结果403 Forbidden。虽然登录了但权限不够。八、刚子小贴士安全避坑指南HTTPS 是必须的JWT 默认不加密Token 在网络传输中如果被截获黑客就能冒充用户。唯一的防御手段就是 HTTPS 加密传输。不要存敏感信息Payload 任何人都能解码看到千万别把密码、身份证号存进去。Token 有效期设置合理的过期时间如 2 小时。为了体验通常会配合“Refresh Token”刷新令牌机制这属于进阶话题感兴趣的同学可以自行研究。配置文件管理不要把密钥硬编码在代码里请迁移到appsettings.json的Jwt:Key配置项中并使用IConfiguration读取。九、总结与下篇预告在这篇文章中我们完成了系统的安全闭环理解了 JWT 的原理Header、Payload、Signature。实现了/login接口颁发 Token。配置了中间件验证 Token。学会了RequireAuthorization和基于角色的权限控制。现在的应用已经是一个功能完备、安全可靠的系统了下一篇预告代码写完了安全也加了最后一步就是让它真正跑在服务器上。 在第八篇最终篇中刚子将带你进入容器化部署的世界。我们将编写 Dockerfile把应用打包成 Docker 镜像并在容器中运行。这标志着你从“开发模式”正式迈入“交付模式”。最后一公里我们下期见原文链接.NET 8 Web开发入门七安全门禁——JWT 身份验证与授权实战 - 码农刚子的开发笔记合集: .NET 8 现代Web开发实战指南标签: JWT, JSON Web Token, 身份验证, 授权, 接口安全, Bearer Token, .NET 8 Security免责声明本内容来自平台创作者博客园系信息发布平台仅提供信息存储空间服务。好文要顶 关注我 收藏该文 微信分享编辑码农刚子粉丝 - 61 关注 - 11加关注3« 上一篇 .NET 8 Web开发入门六Blazor 全栈开发——告别 JavaScript 焦虑» 下一篇 EF Core 8 SQL ServerContains() 突然报 关键字 WITH 附近有语法错误一篇避坑指南posted 2026-06-04 07:57 码农刚子 阅读(420) 评论(0) 收藏 举报