前言
上一节我们讲述的书如何使用jwt token,而且上一节的token是要加Authorization:bearer XXXXXXXXXXXX才能访问。
这一节我们来研究如何自定义类似jwt的token验证,也就是说直接从header中拿取我们想要的token
自己定制JWT
首先,继续在上一节的JwtAuthSample项目中的Startup.cs中的ConfigureServices方法中注释掉以下内容,然后自定义jwt token
public void ConfigureServices(IServiceCollection services){//将appsettings.json中的JwtSettings部分文件读取到JwtSettings中,这是给其他地方用的services.Configure<JwtSettings>(Configuration.GetSection("JwtSettings"));//由于初始化的时候我们就需要用,所以使用Bind的方式读取配置//将配置绑定到JwtSettings实例中var jwtSettings=new JwtSettings();Configuration.Bind("JwtSettings",jwtSettings);services.AddAuthentication(options=>{//认证middleware配置options.DefaultAuthenticateScheme=JwtBearerDefaults.AuthenticationScheme;options.DefaultChallengeScheme=JwtBearerDefaults.AuthenticationScheme;}).AddJwtBearer(o=>{// //主要是jwt token参数设置// o.TokenValidationParameters=new Microsoft.IdentityModel.Tokens.TokenValidationParameters{// ValidIssuer =jwtSettings.Issuer,// ValidAudience =jwtSettings.Audience,// //这里的key要进行加密,需要引用Microsoft.IdentityModel.Tokens// IssuerSigningKey=new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.SecretKey))// };o.SecurityTokenValidators.Clear();//将SecurityTokenValidators清除掉,否则它会在里面拿验证o.Events=new JwtBearerEvents{//重写OnMessageReceivedOnMessageReceived=context=>{var token=context.Request.Headers["mytoken"];context.Token=token.FirstOrDefault();return Task.CompletedTask;}};});services.AddMvc();}
接下来我们新建MyTokenValidator.cs类来验证token,并让这个类实现ISecurityTokenValidator接口
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Microsoft.AspNetCore.Authentication.JwtBearer; using System.Security.Claims; using Microsoft.IdentityModel.Tokens;namespace JwtAuthSample {public class MyTokenValidator : ISecurityTokenValidator{bool ISecurityTokenValidator.CanValidateToken =>true;int ISecurityTokenValidator.MaximumTokenSizeInBytes { get; set; }bool ISecurityTokenValidator.CanReadToken(string securityToken){return true;}//验证tokenClaimsPrincipal ISecurityTokenValidator.ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken){validatedToken=null;//判断token是否正确if(securityToken!="abcdefg")return null;//给Identity赋值var identity=new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme);identity.AddClaim(new Claim("name","wyt"));identity.AddClaim(new Claim(ClaimsIdentity.DefaultRoleClaimType,"admin"));var principle=new ClaimsPrincipal(identity);return principle;}}}
然后我们在Startup.cs的ConfigureServices方法中将我们自定义的MyTokenValidator验证加进去
o.SecurityTokenValidators.Add(new MyTokenValidator());
这时候我们执行dotnet watch run运行项目,用postman不加header头或加错误的hearder头,发现无法访问
我们用正确的自定义token进行访问
Role以及Claims授权
Role授权
我们之前的授权方式都是添加 [Authorize] 标签但是由于我们在Claim中设置了Role
所以我们可以将 [Authorize] 标签写成[Authorize(Roles="admin")]
只有解析出来的token中的角色为admin才授权成功
Claims授权
要使用Claims授权,我们首先需要在Startup.cs的ConfigureServices方法中添加授权
//添加Claim授权services.AddAuthorization(options=>{options.AddPolicy("SuperAdminOnly",policy=>{policy.RequireClaim("SuperAdminOnly");});});
然后在AuthorizeController.cs生成token的action中的Claim中添加SuperAdminOnly
最后在需要权限认证的地方使用标签 [Authorize(Policy="SuperAdminOnly")]
我们首先获取一下token,到jwt官网上解析一下发现token中包含SuperAdminOnly
然后访问成功