以前接触过,写过博客,第二次再写有了新的体会。第一次博客:https://www.cnblogs.com/zhang-3/p/16184067.html
过程:
1.引入包:System.IdentityModel.Tokens.Jwt
这次博客比第一次简化了好多,比如令牌的model类,密钥写在配置文件等,暂时省略了
public static string IssueJwt(string id,string Name) { string iss = "发行人"; string aud = "受众人"; string secret = "12345678912345671234567891234567"; //载荷 var claims = new List<Claim>() { //jwtID唯一 new Claim(JwtRegisteredClaimNames.Jti,id), //发行人可以理解为网站属于发行人 new Claim(JwtRegisteredClaimNames.Iss,iss), //受众可以理解为哪些人可以使用 new Claim(JwtRegisteredClaimNames.Aud,aud), //主体可以理解为对令牌的说明 new Claim(JwtRegisteredClaimNames.Sub,"主体"), //发行时间即为令牌生成的时间 new Claim (JwtRegisteredClaimNames.Iat,$"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"), //在此时间之前不可用 new Claim(JwtRegisteredClaimNames.Nbf,$"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"), //令牌过期时间 new Claim(JwtRegisteredClaimNames.Exp,$"{new DateTimeOffset(DateTime.Now.AddSeconds(60)).ToUnixTimeSeconds()}"), new Claim(ClaimTypes.Name,Name) }; //使用密钥生成签名凭证 var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret)); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); //序列化jwt var jwt = new JwtSecurityTokenHandler().WriteToken( new JwtSecurityToken( issuer: iss, claims: claims, signingCredentials: creds)); return jwt; }
2.引入包:Microsoft.AspNetCore.Authentication.JwtBearer
//注册bearer认证 builder.Services.AddAuthentication(options => { options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(o => { var SigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("12345678912345671234567891234567")); //验证的参数 o.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters { //验证密钥 ValidateIssuerSigningKey = true, IssuerSigningKey = SigningKey, //验证发行者 ValidateIssuer = true, ValidIssuer = "发行人", //验证受众 ValidateAudience = true, ValidAudience = "受众人", //验证有效期 ValidateLifetime = true, ClockSkew = TimeSpan.FromSeconds(30), //必须有过期值/时间 RequireExpirationTime = true }; o.Events = new JwtBearerEvents() { //当JWT Bearer认证失败时,即请求未包含有效的JWT令牌或令牌验证失败,该事件会被触发 OnChallenge = context => { context.Response.Headers.Add("Token-Error", context.ErrorDescription); return Task.CompletedTask; }, //当JWT Bearer认证过程中出现异常时,例如令牌过期、签名验证失败等情况,该事件会被触发 OnAuthenticationFailed = context => { var jwtHandler = new JwtSecurityTokenHandler(); var token = context.Request.Headers["Authorization"].ObjToString().Replace("Bearer ", string.Empty).Replace("bearer",string.Empty).Trim(); var jwtToken = jwtHandler.ReadJwtToken(token); if (jwtToken.Issuer != "发行人") { context.Response.Headers.Add("Token-Error-Iss", "issuer is wrong!"); } if (jwtToken.Audiences.FirstOrDefault() != "受众人") { context.Response.Headers.Add("Token-Error-Aud", "Audience is wrong!"); } // 如果过期,则把<是否过期>添加到,返回头信息中 if (context.Exception.GetType() == typeof(SecurityTokenExpiredException)) { context.Response.Headers.Add("Token-Expired", "true"); } return Task.CompletedTask; } }; });
3和4:引入包:SwashBuckle.AspNetCore.Filters
builder.Services.AddSwaggerGen(a => { // 开启加权小锁(暂时不知道什么意思) a.OperationFilter<AddResponseHeadersFilter>(); //(接口显示认证角色信息) a.OperationFilter<AppendAuthorizeToSummaryOperationFilter>(); // 在header中添加token,传递到后台(添加小锁) a.OperationFilter<SecurityRequirementsOperationFilter>(); a.AddSecurityDefinition("oauth2", new Microsoft.OpenApi.Models.OpenApiSecurityScheme { Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}(注意两者之间是一个空格)\"", Name = "Authorization", //jwt默认的参数名称 In = ParameterLocation.Header, //jwt默认存放Authorization信息的位置(请求头中) Type = SecuritySchemeType.ApiKey//安全方案/类型(模式)APIkey }); });