news 2026/9/3 1:20:01

c#进阶疗法 -jwt+授权

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
c#进阶疗法 -jwt+授权

ASP.NET Core JWT 认证与授权实战指南

什么是 JWT?

JWT(JSON Web Token)是一种基于 JSON 的开放标准(RFC 7519),用于在各方之间安全地传输信息。JWT 可以被验证和信任,因为它是数字签名的。

JWT 通常由三部分组成,用点(.)分隔:

  1. 头部(Header):包含令牌的类型和使用的签名算法。
  2. 载荷(Payload):包含声明(claims),如用户 ID、角色等。
  3. 签名(Signature):用于验证令牌的完整性。

一个典型的 JWT 看起来像这样:

example.jwt.io

为什么需要 JWT?

在传统的认证系统中,服务器通常会在会话中存储用户信息,并向客户端发送一个会话 ID。客户端在后续的请求中使用这个会话 ID 来标识自己。这种方式有以下缺点:

  1. 服务器端存储:服务器需要存储会话信息,这会增加服务器的负担。
  2. 水平扩展困难:如果应用程序部署在多个服务器上,需要在服务器之间共享会话信息,这会增加系统的复杂性。
  3. 跨域问题:在跨域请求中,会话 cookie 可能会被阻止。

JWT 解决了这些问题,因为:

  1. 无状态:JWT 包含了所有必要的信息,服务器不需要存储会话信息。
  2. 易于水平扩展:由于服务器不需要存储会话信息,应用程序可以轻松地部署在多个服务器上。
  3. 跨域友好:JWT 可以通过 HTTP 头在不同域之间传递。

如何使用 JWT 实现认证和授权?

在 ASP.NET Core 中,我们可以使用Microsoft.AspNetCore.Authentication.JwtBearer包来实现 JWT 认证和授权。下面我们将通过具体的示例来演示如何使用 JWT 实现认证和授权。

步骤 1:安装必要的包

首先,我们需要在项目中安装必要的包:

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer dotnet add package System.IdentityModel.Tokens.Jwt dotnet add package Microsoft.Extensions.Options

步骤 2:创建 JWT 相关类

2.1 创建 JwtSettings 类

首先,我们创建一个JwtSettings类,用于存储 JWT 的配置选项:

namespaceFrameLearning.BasicComponents.Jwt{publicclassJwtSettings{publicstringSecret{get;set;}publicstringIssuer{get;set;}publicstringAudience{get;set;}publicintExpirationInMinutes{get;set;}}}

在这个示例中,我们创建了一个JwtSettings类,它包含SecretIssuerAudienceExpirationInMinutes四个属性,用于存储 JWT 的密钥、颁发者、受众和过期时间。

2.2 创建 UserCredentials 类

接下来,我们创建一个UserCredentials类,用于存储登录请求的数据:

namespaceFrameLearning.BasicComponents.Jwt{publicclassUserCredentials{publicstringUsername{get;set;}publicstringPassword{get;set;}}}

在这个示例中,我们创建了一个UserCredentials类,它包含UsernamePassword两个属性,用于存储用户的用户名和密码。

2.3 创建 UserResponse 类

然后,我们创建一个UserResponse类,用于存储登录响应的数据:

namespaceFrameLearning.BasicComponents.Jwt{publicclassUserResponse{publicstringUsername{get;set;}publicstringToken{get;set;}publicList<string>Roles{get;set;}}}

在这个示例中,我们创建了一个UserResponse类,它包含UsernameTokenRoles三个属性,用于存储用户的用户名、JWT 令牌和角色。

2.4 创建 IJwtService 接口和 JwtService 类

最后,我们创建一个IJwtService接口和JwtService类,用于生成和验证 JWT 令牌:

usingMicrosoft.Extensions.Options;usingMicrosoft.IdentityModel.Tokens;usingSystem.IdentityModel.Tokens.Jwt;usingSystem.Security.Claims;usingSystem.Text;namespaceFrameLearning.BasicComponents.Jwt{publicinterfaceIJwtService{stringGenerateToken(stringusername,List<string>roles);ClaimsPrincipalValidateToken(stringtoken);}publicclassJwtService:IJwtService{privatereadonlyJwtSettings_jwtSettings;publicJwtService(IOptions<JwtSettings>jwtSettings){_jwtSettings=jwtSettings.Value;}publicstringGenerateToken(stringusername,List<string>roles){// 验证 JwtSettings 的属性是否为 nullif(string.IsNullOrEmpty(_jwtSettings.Secret)){thrownewException("JwtSettings.Secret 不能为空");}if(string.IsNullOrEmpty(_jwtSettings.Issuer)){thrownewException("JwtSettings.Issuer 不能为空");}if(string.IsNullOrEmpty(_jwtSettings.Audience)){thrownewException("JwtSettings.Audience 不能为空");}if(_jwtSettings.ExpirationInMinutes<=0){_jwtSettings.ExpirationInMinutes=30;// 默认 30 分钟}varclaims=newList<Claim>{newClaim(ClaimTypes.Name,username),newClaim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString())};// 添加角色声明foreach(varroleinroles){claims.Add(newClaim(ClaimTypes.Role,role));}varkey=newSymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettings.Secret));varcreds=newSigningCredentials(key,SecurityAlgorithms.HmacSha256);vartoken=newJwtSecurityToken(issuer:_jwtSettings.Issuer,audience:_jwtSettings.Audience,claims:claims,expires:DateTime.Now.AddMinutes(_jwtSettings.ExpirationInMinutes),signingCredentials:creds);returnnewJwtSecurityTokenHandler().WriteToken(token);}publicClaimsPrincipalValidateToken(stringtoken){vartokenHandler=newJwtSecurityTokenHandler();varkey=Encoding.UTF8.GetBytes(_jwtSettings.Secret);try{varprincipal=tokenHandler.ValidateToken(token,newTokenValidationParameters{ValidateIssuerSigningKey=true,IssuerSigningKey=newSymmetricSecurityKey(key),ValidateIssuer=true,ValidateAudience=true,ValidIssuer=_jwtSettings.Issuer,ValidAudience=_jwtSettings.Audience,ValidateLifetime=true,ClockSkew=TimeSpan.Zero},outSecurityTokenvalidatedToken);varjwtToken=(JwtSecurityToken)validatedToken;if(jwtToken.ValidTo<DateTime.UtcNow){thrownewSecurityTokenExpiredException("Token has expired");}returnprincipal;}catch{returnnull;}}}}

在这个示例中,我们创建了一个IJwtService接口,它定义了GenerateTokenValidateToken两个方法,用于生成和验证 JWT 令牌。然后,我们创建了一个JwtService类,它实现了IJwtService接口的方法。在GenerateToken方法中,我们首先验证JwtSettings的属性是否为 null,然后创建声明列表,添加角色声明,创建密钥和签名凭据,创建 JWT 令牌,最后返回令牌字符串。在ValidateToken方法中,我们首先创建令牌处理器和密钥,然后验证令牌,最后返回声明主体。

步骤 3:配置 JWT 认证和授权

Program.cs文件中,我们需要配置 JWT 认证和授权:

// 配置 JWTbuilder.Services.Configure<JwtSettings>(builder.Configuration.GetSection("JwtSettings"));// 注册服务builder.Services.AddScoped<IJwtService,JwtService>();// 添加 JWT 认证和授权builder.Services.AddAuthentication(options=>{options.DefaultAuthenticateScheme=JwtBearerDefaults.AuthenticationScheme;options.DefaultChallengeScheme=JwtBearerDefaults.AuthenticationScheme;}).AddJwtBearer(options=>{options.TokenValidationParameters=newTokenValidationParameters{ValidateIssuer=true,ValidateAudience=true,ValidateLifetime=true,ValidateIssuerSigningKey=true,ValidIssuer=builder.Configuration["JwtSettings:Issuer"],ValidAudience=builder.Configuration["JwtSettings:Audience"],IssuerSigningKey=newSymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["JwtSettings:Secret"]))};// 需要指定 JWT 角色映射关系options.TokenValidationParameters.RoleClaimType=ClaimTypes.Role;options.Events=newJwtBearerEvents{OnChallenge=asynccontext=>{// 跳过默认响应context.HandleResponse();context.Response.StatusCode=StatusCodes.Status401Unauthorized;context.Response.ContentType="application/json";ApiResponse<object>apiResponse=newApiResponse<object>();apiResponse.Code=401;apiResponse.Message=context.ErrorDescription??"提供的令牌无效";apiResponse.Data=null;apiResponse.Success=false;awaitcontext.Response.WriteAsync(JsonSerializer.Serialize(apiResponse));}};});builder.Services.AddAuthorization();

在这个示例中,我们首先配置JwtSettings,然后注册IJwtService服务,接着添加 JWT 认证和授权,最后注册授权服务。在添加 JWT 认证时,我们配置了令牌验证参数,包括验证颁发者、受众、过期时间和签名密钥,以及指定 JWT 角色映射关系。我们还配置了OnChallenge事件,用于自定义未授权响应。

步骤 4:添加登录端点

在控制器中,我们需要添加一个登录端点,用于生成和返回 JWT 令牌:

[HttpPost("login")][AllowAnonymous]publicIActionResultLogin([FromBody]UserCredentialscredentials){varroles=_userServer.GetRoles();// 生成tokenvartoken=_jwtService.GenerateToken(credentials.Username,roles);returnOk(newUserResponse{Username=credentials.Username,Token=token,Roles=roles});}

在这个示例中,我们添加了一个Login方法,它接受一个UserCredentials对象作为参数,然后获取用户角色,生成 JWT 令牌,最后返回一个UserResponse对象,包含用户名、令牌和角色。

步骤 5:添加授权保护的端点

在控制器中,我们可以添加一些需要授权才能访问的端点:

[HttpGet][Authorize(Roles="Admin")]publicIActionResultGet(){varforecasts=Enumerable.Range(1,5).Select(index=>newWeatherForecast{Date=DateOnly.FromDateTime(DateTime.Now.AddDays(index)),TemperatureC=Random.Shared.Next(-20,55),Summary=Summaries[Random.Shared.Next(Summaries.Length)]}).ToArray();returnOk(forecasts);}

在这个示例中,我们添加了一个Get方法,它使用[Authorize(Roles = "Admin")]特性标记,表明只有具有Admin角色的用户才能访问这个方法。

配置 JWT 设置

appsettings.json文件中,我们需要配置 JWT 设置:

{"JwtSettings":{"Secret":"X7gT$pL2@mKq9!vN5&sF8*oU4^jH6%zR","Issuer":"TestApi","Audience":"TestApiUsers","ExpirationInMinutes":60}}

在这个示例中,我们配置了 JWT 的密钥、颁发者、受众和过期时间。

测试 JWT 认证和授权

步骤 1:获取 JWT 令牌

首先,我们需要发送一个 POST 请求到登录端点,获取 JWT 令牌:

POST /weatherforecast/login Content-Type: application/json { "username": "John", "password": "126.com" }

响应应该类似于:

{"username":"John","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiSm9obiIsImp0aSI6ImI3MDExYjZlLTZhZTQtNDgxMS05MGFlLWQxMDBkNjA5M2JmOSIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvcm9sZSI6IkFkbWluIiwiZXhwIjoxNzY4OTAwOTc4LCJpc3MiOiJUZXN0QXBpIiwiYXVkIjoiVGVzdEFwaVVzZXJzIn0.nggbL8AmiYEejRAFZzCX6Xhv5dAuNGfjy45hQ7d225o","roles":["Admin"]}

步骤 2:使用 JWT 令牌访问受保护的端点

然后,我们可以使用获取到的 JWT 令牌访问受保护的端点:

GET /weatherforecast Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiSm9obiIsImp0aSI6ImI3MDExYjZlLTZhZTQtNDgxMS05MGFlLWQxMDBkNjA5M2JmOSIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvcm9sZSI6IkFkbWluIiwiZXhwIjoxNzY4OTAwOTc4LCJpc3MiOiJUZXN0QXBpIiwiYXVkIjoiVGVzdEFwaVVzZXJzIn0.nggbL8AmiYEejRAFZzCX6Xhv5dAuNGfjy45hQ7d225o

响应应该类似于:

[{"date":"2026-01-22","temperatureC":12,"temperatureF":53,"summary":"Mild"},{"date":"2026-01-23","temperatureC":23,"temperatureF":73,"summary":"Warm"},{"date":"2026-01-24","temperatureC":-5,"temperatureF":23,"summary":"Freezing"},{"date":"2026-01-25","temperatureC":34,"temperatureF":93,"summary":"Hot"},{"date":"2026-01-26","temperatureC":18,"temperatureF":64,"summary":"Balmy"}]

步骤 3:测试未授权访问

如果我们不提供 JWT 令牌或者提供的令牌无效,访问受保护的端点应该返回未授权响应:

GET /weatherforecast

响应应该类似于:

{"code":401,"success":false,"data":null,"message":"提供的令牌无效"}

JWT 和授权的最佳实践

1. 安全存储密钥

JWT 密钥应该安全存储,不应该硬编码在代码中或者存储在版本控制系统中。建议使用环境变量或者密钥管理服务来存储 JWT 密钥。

2. 设置合理的过期时间

JWT 令牌应该设置合理的过期时间,不宜过长也不宜过短。过长的过期时间会增加安全风险,过短的过期时间会影响用户体验。建议根据应用程序的具体需求设置过期时间,通常为 15 分钟到 24 小时之间。

3. 使用 HTTPS

JWT 令牌应该通过 HTTPS 传输,以防止中间人攻击。

4. 验证令牌

在服务器端,每次收到 JWT 令牌时都应该验证令牌的有效性,包括验证签名、过期时间和声明。

5. 实现令牌刷新机制

为了避免用户频繁登录,建议实现令牌刷新机制,允许用户使用过期的令牌换取新的令牌。

6. 限制令牌的使用范围

JWT 令牌应该限制使用范围,只允许访问必要的资源。可以通过在令牌中添加scope声明来实现。

7. 监控和审计

应该监控和审计 JWT 令牌的使用情况,及时发现和处理异常情况。

总结

JWT 是一种基于 JSON 的开放标准,用于在各方之间安全地传输信息。在 ASP.NET Core 中,我们可以使用Microsoft.AspNetCore.Authentication.JwtBearer包来实现 JWT 认证和授权。

通过本文的示例,我们学习了如何:

  1. 创建 JWT 相关类,包括JwtSettingsUserCredentialsUserResponseIJwtServiceJwtService
  2. 配置 JWT 认证和授权。
  3. 添加登录端点,用于生成和返回 JWT 令牌。
  4. 添加授权保护的端点,需要授权才能访问。
  5. 配置 JWT 设置。
  6. 测试 JWT 认证和授权。

我们还学习了 JWT 和授权的最佳实践,包括安全存储密钥、设置合理的过期时间、使用 HTTPS、验证令牌、实现令牌刷新机制、限制令牌的使用范围,以及监控和审计。

希望本文对你理解和使用 ASP.NET Core JWT 认证和授权有所帮助!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 21:36:15

导师严选10个AI论文平台,专科生毕业论文轻松搞定!

导师严选10个AI论文平台&#xff0c;专科生毕业论文轻松搞定&#xff01; AI 工具助力论文写作&#xff0c;专科生也能轻松应对 在当前的学术环境中&#xff0c;越来越多的专科生开始借助 AI 工具来完成毕业论文的撰写。这些工具不仅能够帮助学生快速生成初稿&#xff0c;还能在…

作者头像 李华
网站建设 2026/9/2 23:50:35

如何让Python程序在任何Windows电脑运行?这个方法太高效了!

第一章&#xff1a;Python程序打包成EXE的核心价值将Python程序打包为可执行文件&#xff08;EXE&#xff09;是提升应用部署效率和用户体验的关键步骤。对于开发者而言&#xff0c;这一过程不仅简化了分发流程&#xff0c;还降低了终端用户运行程序的技术门槛。消除环境依赖 许…

作者头像 李华
网站建设 2026/9/2 23:12:01

还在为提取链接发愁?1个正则搞定所有网页URL抓取场景

第一章&#xff1a;正则表达式提取网页链接的核心价值 在现代Web数据处理中&#xff0c;从非结构化HTML文本中高效提取有效链接是信息采集、搜索引擎优化和自动化测试的关键环节。正则表达式作为一种强大的文本匹配工具&#xff0c;能够在不依赖完整解析器的情况下快速定位URL模…

作者头像 李华
网站建设 2026/9/2 22:26:40

工业控制领域中的经典系统建模与控制实现

单容/双容水箱液位控制系统建模&#xff0c;PID控制&#xff1b;酸碱中和控制器&#xff1b;在自动化控制的世界里&#xff0c;单容/双容水箱液位控制系统建模以及酸碱中和控制器&#xff0c;都是非常经典且实用的案例。今天咱们就一起来深入探究一番。 单容/双容水箱液位控制系…

作者头像 李华
网站建设 2026/9/2 23:52:18

【Java跨域问题终极解决方案】:CORS配置全解析与实战技巧

第一章&#xff1a;Java跨域问题概述在现代Web开发中&#xff0c;前后端分离架构已成为主流模式&#xff0c;前端通过HTTP请求与后端Java服务进行数据交互。然而&#xff0c;由于浏览器的同源策略&#xff08;Same-Origin Policy&#xff09;限制&#xff0c;当请求的协议、域名…

作者头像 李华
网站建设 2026/9/2 11:15:50

亚马逊绿标:不止大促流量,更是品牌复购的长期护城河

一、品牌增强&#xff1a;从流量标签到价值资产&#xff0c;形成差异化护城河官方权威信任背书绿标是亚马逊 “气候友好承诺” 的官方认证&#xff0c;代表产品通过 FSC/GRS/ 碳中和等权威标准&#xff0c;快速消除消费者环保信任成本&#xff0c;尤其在欧美市场&#xff0c;83…

作者头像 李华