JWT 身份验证
- 引言
- 引用依赖包
- 添加身份认证相关服务到容器中
- swagger 中配置JWT
- 开启中间件
- 生成Token
- 获取claims中的参数信息
- 接口中添加[Authorize()]
- jwt 自定义策略
引言
JWT定义与优缺点
引用依赖包
Microsoft.AspNetCore.Authentication.JwtBearer
System.IdentityModel.Tokens.Jwt
添加身份认证相关服务到容器中
在 Startup.cs 文件 ConfigureServices 方法中 添加服务
services.AddAuthentication(x=>
{x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(jwtOptions =>
{byte[] btKey = Encoding.UTF8.GetBytes(AppSettingHelper.JsonWebTokenDto.Secret);SecurityKey securityKey = new SymmetricSecurityKey(btKey);jwtOptions.TokenValidationParameters = new TokenValidationParameters{IssuerSigningKey = securityKey,//将用于检查令牌的发行者是否与此发行者相同。ValidIssuer = AppSettingHelper.JsonWebTokenDto.Issuer,//是否验证发行者ValidateIssuer = AppSettingHelper.JsonWebTokenDto.ValidateIssuer,//检查令牌的受众群体是否与此受众群体相同。ValidAudience = AppSettingHelper.JsonWebTokenDto.Audience,//在令牌验证期间验证受众 .ValidateAudience = AppSettingHelper.JsonWebTokenDto.ValidateAudience,//验证生命周期ValidateLifetime = true,// The signing key must match!//是否调用对签名securityToken的SecurityKey进行验证。ValidateIssuerSigningKey = true,// If you want to allow a certain amount of clock drift, set that here:ClockSkew = TimeSpan.Zero};});
swagger 中配置JWT
net core 3.1 搭建 swagger
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{Name = "Authorization",Type = SecuritySchemeType.ApiKey,Scheme = "Bearer",BearerFormat = "JWT",In = ParameterLocation.Header,Description = "Token(Bearer)令牌" //JWT Authorization header using the Bearer scheme.
});
//swagger 每次请求 Authorization
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{{new OpenApiSecurityScheme{Reference = new OpenApiReference{Type = ReferenceType.SecurityScheme,Id = "Bearer"}},new string[] {}}
});
开启中间件
在 Startup.cs 文件中的 Configure 方法中 开启中间件
app.UseAuthentication();
注意:放在 app.UseAuthorization()前边
生成Token
public string CreateToken(TeacherDto dto)
{var claims = new Claim[]{new Claim(JwtRegisteredClaimNames.Sub, dto.UserName), //用户 new Claim(JwtRegisteredClaimNames.Jti, dto.Id.ToString()), //编号new Claim(nameof(dto.Name), dto.Name) //名字};// Create the JWT and write it to a stringbyte[] btKey = Encoding.UTF8.GetBytes(AppSettingHelper.JsonWebTokenDto.Secret);SecurityKey securityKey = new SymmetricSecurityKey(btKey);DateTime dtNow = DateTime.Now;var jwt = new JwtSecurityToken(issuer: AppSettingHelper.JsonWebTokenDto.Issuer,audience: AppSettingHelper.JsonWebTokenDto.Audience,claims: claims,notBefore: dtNow,expires: dtNow.AddMinutes(AppSettingHelper.JsonWebTokenDto.Expires),signingCredentials: new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256));//IdentityModelEventSource.ShowPII = true;var token = new JwtSecurityTokenHandler().WriteToken(jwt);return token;
}
获取claims中的参数信息
1、Startup 构造函数中将默认映射方式给移除掉
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
2、使用此命令获取值
HttpContext.User.FindFirst(d => d.Type == JwtRegisteredClaimNames.Sub)?.Value;
接口中添加[Authorize()]
jwt 自定义策略
自定义策略官方文档
1、新建 xxxRequirement类,继承IAuthorizationRequirement
2、新建 xxxAuthorizationHandler ,继承AuthorizationHandler<xxxRequirement>,重写 HandleRequirementAsync方法
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, JsonWebTokenRequirement requirement)
{//是否经过验证var isAuthenticated = context?.User?.Identity?.IsAuthenticated ?? false;if (!isAuthenticated){context.Fail(); // 显式的声明验证失败 }else{context.Succeed(requirement); // 显式的声明验证成功 }return Task.CompletedTask;
}
3、Startup.cs 文件 ConfigureServices 方法添加 自定义策略服务
services.AddAuthorization(auth =>
{auth.AddPolicy("Bearer", policy => policy.Requirements.Add(new Service.Authorization.JsonWebTokenRequirement()));
});
services.AddSingleton<IAuthorizationHandler, Service.Authorization.JsonWebTokenHandler>();
4、接口添加 [Authorize(Policy = “Bearer”)]