.net 8 Web Api 集成 Jwt,通过swagger获取token,验证是否有权限访问资源

简易介绍.net 8 Web Api 集成 Jwt,配合Authentication和Authorization中间件实现用户身份认证与与是否有权限访问资源验证。通过Swagger进行接口校验。

1、创建.net 8 Web Api 项目

2、添加Jwt包,版本要与.net版本对应

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer 8.0

3、配置服务

 1 public class Program
 2 {
 3     public static void Main(string[] args)
 4     {
 5         var builder = WebApplication.CreateBuilder(args);
 6 
 7         // Add services to the container.
 8         builder.Services.AddSingleton(new JwtHelper(builder.Configuration));
 9 
10         builder.Services.AddControllers();
11         // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
12         builder.Services.AddEndpointsApiExplorer();
13 
14         //添加身份认证
15         builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
16         {
17             options.TokenValidationParameters = new TokenValidationParameters
18             {
19                 ValidateIssuer = true,               // 验证令牌的签发者
20                 ValidIssuer = builder.Configuration["Jwt:Issuer"],
21                 ValidateAudience = false,             // 验证令牌的接收者
22                 //ValidAudience = "your-audience",     // 接收者
23                 ValidateLifetime = true,             // 验证令牌的过期时间
24                 ValidateIssuerSigningKey = true,     // 验证签名密钥
25                 IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:SecKey"])), // 加密密钥
26                 ClockSkew = TimeSpan.FromSeconds(30), //过期时间容错值,解决服务器端时间不同步问题(秒)
27                 RequireExpirationTime = true,
28             };
29         });
30         // 添加 Swagger 
31         builder.Services.AddSwaggerGen(c =>
32         {
33             c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
34             {
35                 Description = "输入 JWT(格式: Bearer {token})",
36                 Name = "Authorization",
37                 In = ParameterLocation.Header,
38                 Type = SecuritySchemeType.Http,
39                 Scheme = "bearer"
40             });
41             c.AddSecurityRequirement(new OpenApiSecurityRequirement {
42             { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } }, new string[] { } }
43             });
44         });
45 
46         var app = builder.Build();
47 
48         // Configure the HTTP request pipeline.
49         if (app.Environment.IsDevelopment())
50         {
51             app.UseSwagger();
52             app.UseSwaggerUI();
53         }
54 
55         app.UseHttpsRedirection();
56 
57         app.UseAuthentication();// 1. 身份验证中间件,用于检查请求的身份认证信息
58 
59         app.UseAuthorization();// 2. 授权中间件,用于检查用户的权限
60 
61         app.MapControllers();
62 
63         app.Run();
64     }
65 }

4、配置文件

 1 {
 2   "JWT": {
 3     "SecKey": "Jamin1127!#@$%@%^^&*(~Czmjklneafguvioszb%yuv&*6WVDf5dw#5dfw6f5w6faW%FW^f5wa65f^AWf56", //密钥
 4     "Issuer": "Jamin", //发行者
 5     "Audience": "LL",//接收者
 6     "ExpireSeconds": 7200 //过期时间
 7   },
 8   "Account": {
 9     "userName": "admin",
10     "password": "1q2w3E*"
11   },
12   "Logging": {
13     "LogLevel": {
14       "Default": "Information",
15       "Microsoft.AspNetCore": "Warning"
16     }
17   },
18   "AllowedHosts": "*"
19 }
View Code

5、添加获取和验证token的Controller

 1 [ApiController]
 2 [Route("[controller]")]
 3 public class UserController : ControllerBase
 4 {
 5     private readonly JwtHelper _jwtHelper;
 6     private readonly IConfiguration _configuration;
 7 
 8     public UserController(JwtHelper jwtHelper, IConfiguration configuration)
 9     {
10         _jwtHelper = jwtHelper;
11         _configuration = configuration;
12     }
13 
14     /// <summary>
15     /// 获取Token
16     /// </summary>
17     /// <returns></returns>
18     [HttpPost("GetToken")]
19     public IActionResult GetToken(string userName, [PasswordPropertyText] string password, string mobile)
20     {
21         //参数验证等等....
22         if (string.IsNullOrEmpty(userName))
23         {
24             return Ok("参数异常!");
25         }
26         UserInfo user = new UserInfo()
27         {
28             Password = password,
29             UserName = userName,
30             PhoneNumber = mobile
31         };
32 
33         //这里可以连接mysql数据库做账号密码验证
34         if (user.UserName != _configuration["Account:userName"] || user.Password != _configuration["Account:password"])
35         {
36             return Ok("账户或者密码错误!");
37         }
38 
39         //这里可以做Redis缓存验证等等
40 
41 
42         //这里获取Token,当然,这里也可以选择传结构体过去
43         var token = _jwtHelper.CreateToken(user.UserName, user.PhoneNumber);
44         //解密后的Token
45         //var PWToken = _jwtHelper.JwtDecrypt(token);
46         return Ok(token);
47     }
48 
49     /// <summary>
50     /// 获取自己的详细信息,其中 [Authorize] 就表示要带Token才行
51     /// </summary>
52     /// <returns></returns>
53     [HttpPost("GetSelfInfo")]
54     [Authorize]
55     public IActionResult GetSelfInfo()
56     {
57         //执行到这里,就表示已经验证授权通过了
58         /*
59          * 这里返回个人信息有两种方式
60          * 第一种:从Header中的Token信息反向解析出用户账号,再从数据库中查找返回
61          * 第二种:从Header中的Token信息反向解析出用户账号信息直接返回,当然,在前面创建        Token时,要保存进使用到的Claims中。
62         */
63         return Ok("授权通过了!");
64     }
65 }
View Code

6、JwtHelper类

  1 public class JwtHelper
  2 {
  3     private readonly IConfiguration _configuration;
  4 
  5     public JwtHelper(IConfiguration configuration)
  6     {
  7         _configuration = configuration;
  8     }
  9 
 10     /// <summary>
 11     /// 创建Token 这里面可以保存自己想要的信息
 12     /// </summary>
 13     /// <param name="username"></param>
 14     /// <param name="mobile"></param>
 15     /// <returns></returns>
 16     public string CreateToken(string username, string mobile)
 17     {
 18         try
 19         {
 20             // 1. 定义需要使用到的Claims
 21             var claims = new[]
 22             {
 23                 new Claim("username", username),
 24                 new Claim("mobile", mobile),
 25                 /* 可以保存自己想要信息,传参进来即可
 26                 new Claim("sex", "sex"),
 27                 new Claim("limit", "limit"),
 28                 new Claim("head_url", "xxxxx")
 29                 */
 30             };
 31 
 32             // 2. 从 appsettings.json 中读取SecretKey
 33             var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:SecKey"]));
 34 
 35             // 3. 选择加密算法
 36             var algorithm = SecurityAlgorithms.HmacSha256;
 37 
 38             // 4. 生成Credentials
 39             var signingCredentials = new SigningCredentials(secretKey, algorithm);
 40 
 41             // 5. 根据以上,生成token
 42             var jwtSecurityToken = new JwtSecurityToken(
 43                 _configuration["Jwt:Issuer"],    //Issuer
 44                 _configuration["Jwt:ExpireSeconds"],  //ExpireSeconds
 45                 claims,                          //Claims,
 46                 DateTime.Now,                    //notBefore
 47                 DateTime.Now.AddSeconds(30),     //expires
 48                 signingCredentials               //Credentials
 49             );
 50 
 51             // 6. 将token变为string
 52             var token = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
 53 
 54             return token;
 55         }
 56         catch (Exception)
 57         {
 58             throw;
 59         }
 60 
 61     }
 62     /// <summary>
 63     /// 获取信息
 64     /// </summary>
 65     /// <param name="jwt"></param>
 66     /// <returns></returns>
 67     public static string ReaderToken(string jwt)
 68     {
 69         var str = string.Empty;
 70         try
 71         {
 72             //获取Token的三种方式
 73             //第一种直接用JwtSecurityTokenHandler提供的read方法
 74             var jwtHander = new JwtSecurityTokenHandler();
 75             JwtSecurityToken jwtSecurityToken = jwtHander.ReadJwtToken(jwt);
 76             str = jwtSecurityToken.ToString();
 77         }
 78         catch (Exception ex)
 79         {
 80             Debug.WriteLine(ex.Message);
 81         }
 82         return str;
 83     }
 84 
 85     /// <summary>
 86     /// 解密jwt
 87     /// </summary>
 88     /// <param name="jwt"></param>
 89     /// <returns></returns>
 90     public string JwtDecrypt(string jwt)
 91     {
 92 
 93         StringBuilder sb = new StringBuilder();
 94         try
 95         {
 96             JwtSecurityTokenHandler tokenHandler = new();
 97             TokenValidationParameters valParam = new();
 98             var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:SecKey"]));
 99             valParam.IssuerSigningKey = securityKey;
100             valParam.ValidateIssuer = false;
101             valParam.ValidateAudience = false;
102             //解密
103             ClaimsPrincipal claimsPrincipal = tokenHandler.ValidateToken(jwt,
104                     valParam, out SecurityToken secToken);
105             foreach (var claim in claimsPrincipal.Claims)
106             {
107                 sb.Append($"{claim.Type}={claim.Value}");
108             }
109         }
110         catch (Exception ex)
111         {
112             Debug.WriteLine(ex.Message);
113         }
114         return sb.ToString();
115     }
116 }
View Code

7、swagger测试

先调用login获取登录返回的 JWT 令牌,点击“Authorize”按钮,输入生成的 JWT 令牌,格式为 Bearer {token},net8.0不需要手动在前面加Bearer 。然后尝试调用受保护的 API 方法,查看是否成功返回数据。

posted @ 2025-04-23 18:06  是铭不是明  阅读(575)  评论(0)    收藏  举报