NutGet包
- Microsoft.AspNetCore.Authentication.JwtBearer
- Swashbuckle.AspNetCore
Swashbuckle.AspNetCore.Filters
Swagger●添加服务
ConfigureServices中添加
services.AddSwaggerGen(c =>{c.SwaggerDoc("V1", new OpenApiInfo{// {ApiName} 定义成全局变量,方便修改Version = "V1",Title = $"{ApiName} 接口文档——Netcore 3.1",Description = $"{ApiName} HTTP API V1",Contact = new OpenApiContact { Name = ApiName, Email = "你的邮箱", Url = new Uri("你的网址") },License = new OpenApiLicense { Name = ApiName, Url = new Uri("你的网址") }});c.OrderActionsBy(o => o.RelativePath);// 获取xml文件名var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";// 获取xml文件路径var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);// 添加控制器层注释,true表示显示控制器注释//默认的第二个参数是false,这个是controller的注释,记得修改c.IncludeXmlComments(xmlPath, true);var xmlModelPath = Path.Combine(AppContext.BaseDirectory, "Model生成的文件名.xml");//这个就是Model层的xml文件名c.IncludeXmlComments(xmlModelPath);//开启加权小锁c.OperationFilter<AddResponseHeadersFilter>();c.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();//在Heder中添加Token 传递到后台c.OperationFilter<SecurityRequirementsOperationFilter>();c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme{Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}(注意两者之间有一个空格)",Name = "Authorization",//jwt默认的参数名称,In = ParameterLocation.Header,//jwt默认存放Autorization信息的位置(header中)Type = SecuritySchemeType.ApiKey});});
Swagger●配置中间件
Configure中添加
app.UseSwaggerUI(c =>{c.SwaggerEndpoint($"/swagger/V1/swagger.json", $"{ApiName} V1");//路径配置,设置为空,表示直接在根域名(localhost:8001)访问该文件,注意localhost:8001/swagger是访问不到的,去launchSettings.json把launchUrl去掉,如果你想换一个路径,直接写名字即可,比如直接写c.RoutePrefix = "doc";c.RoutePrefix = "";});
JWT●添加服务
ConfigureServices中添加
services.AddAuthentication("Bearer").AddJwtBearer(o => {o.TokenValidationParameters = new TokenValidationParameters{ValidateIssuerSigningKey = true,IssuerSigningKey = “秘钥”,ValidateIssuer = true,ValidIssuer = “”,//发行人ValidateAudience = true,ValidAudience = “”,//订阅人ValidateLifetime = true,ClockSkew = TimeSpan.Zero,//这个是缓冲过期时间,也就是说,即使我们配置了过期时间,这里也要考虑进去,过期时间+缓冲,默认好像是7分钟,你可以直接设置为0RequireExpirationTime = true,};o.Events = new JwtBearerEvents {OnAuthenticationFailed = context => {// 如果过期,则把<是否过期>添加到,返回头信息中if (context.Exception.GetType() == typeof(SecurityTokenExpiredException)){context.Response.Headers.Add("Token-Expired", "true");}return Task.CompletedTask;}};});
JWT●配置中间件
Configure中添加
//先开启认证app.UseAuthentication();//授权中间件app.UseAuthorization();
JWTHelper
封装一个JWThelper 用于生成token ```csharp public class JWTHelper {
public class JwtHelper{/// <summary>/// 颁发JWT字符串/// </summary>/// <param name="tokenModel"></param>/// <returns></returns>public static string IssueJwt(TokenModelJwt tokenModel){// 自己封装的 appsettign.json 操作类,看下文string iss = Appsettings.app(new string[] { "Audience", "Issuer" });string aud = Appsettings.app(new string[] { "Audience", "Audience" });string secret = Appsettings.app(new string[] { "Audience", "Secret" });var claims = new List<Claim>{/** 特别重要:1、这里将用户的部分信息,比如 uid 存到了Claim 中,如果你想知道如何在其他地方将这个 uid从 Token 中取出来,请看下边的SerializeJwt() 方法,或者在整个解决方案,搜索这个方法,看哪里使用了!2、你也可以研究下 HttpContext.User.Claims ,具体的你可以看看 Policys/PermissionHandler.cs 类中是如何使用的。*/new Claim(JwtRegisteredClaimNames.Jti, tokenModel.Uid.ToString()),new Claim(JwtRegisteredClaimNames.Iat, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"),new Claim(JwtRegisteredClaimNames.Nbf,$"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}") ,//这个就是过期时间,目前是过期7200秒,可自定义,注意JWT有自己的缓冲过期时间new Claim (JwtRegisteredClaimNames.Exp,$"{new DateTimeOffset(DateTime.Now.AddSeconds(7200)).ToUnixTimeSeconds()}"),new Claim(JwtRegisteredClaimNames.Iss,iss),new Claim(JwtRegisteredClaimNames.Aud,aud),//new Claim(ClaimTypes.Role,tokenModel.Role),//为了解决一个用户多个角色(比如:Admin,System),用下边的方法};// 可以将一个用户的多个角色全部赋予;// 作者:DX 提供技术支持;claims.AddRange(tokenModel.Role.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));
//秘钥 (SymmetricSecurityKey 对安全性的要求,密钥的长度太短会报出异常)var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);var jwt = new JwtSecurityToken(issuer: iss,claims: claims,signingCredentials: creds//,expires:DateTime.Now.AddMinutes(1));var jwtHandler = new JwtSecurityTokenHandler();var encodedJwt = jwtHandler.WriteToken(jwt);return encodedJwt;}/// <summary>/// 解析/// </summary>/// <param name="jwtStr"></param>/// <returns></returns>public static TokenModelJwt SerializeJwt(string jwtStr){var jwtHandler = new JwtSecurityTokenHandler();JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(jwtStr);object role;try{jwtToken.Payload.TryGetValue(ClaimTypes.Role, out role);}catch (Exception e){Console.WriteLine(e);throw;}var tm = new TokenModelJwt{Uid = (jwtToken.Id).ObjToInt(),Role = role != null ? role.ObjToString() : "",};return tm;}}/// <summary>/// 令牌/// </summary>public class TokenModelJwt{/// <summary>/// Id/// </summary>public long Uid { get; set; }/// <summary>/// 角色/// </summary>public string Role { get; set; }/// <summary>/// 职能/// </summary>public string Work { get; set; }}}
在Controller中可以测试```csharpTokenModelJwt tokenModel = new TokenModelJwt { Uid = 1, Role = userRole };jwtStr = JwtHelper.IssueJwt(tokenModel);//登录,获取到一定规则的 Token 令牌

