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

浙公网安备 33010602011771号