一、通过Jwt获取Token,并通过缓存记录,配合中间件实现验证
在之前的搭建中,swagger已经基本成型,其实其功能之多,不是我这三篇所能写完的,想要添加权限,先从服务开始
在ConfigureServices中,增加以下代码
View Code
最终的是这样的
////// ConfigureServices 方法 //////publicvoid ConfigureServices(IServiceCollection services) { services.AddMvc(); #regionSwagger services.AddSwaggerGen(c => { c.SwaggerDoc("v1",new Info { Version ="v0.1.0", Title ="Blog.Core API", Description ="框架说明文档", TermsOfService ="None", Contact =newSwashbuckle.AspNetCore.Swagger.Contact { Name ="Blog.Core", Email ="Blog.Core@xxx.com", Url ="https://www.jianshu.com/u/94102b59cc2a" } }); //就是这里#region读取xml信息varbasePath = PlatformServices.Default.Application.ApplicationBasePath; varxmlPath = Path.Combine(basePath,"Blog.Core.xml");//这个就是刚刚配置的xml文件名varxmlModelPath = Path.Combine(basePath,"Blog.Core.Model.xml");//这个就是Model层的xml文件名c.IncludeXmlComments(xmlPath,true);//默认的第二个参数是false,这个是controller的注释,记得修改 c.IncludeXmlComments(xmlModelPath); #endregion#regionToken绑定到ConfigureServices//添加header验证信息 //c.OperationFilter();varsecurity =newDictionary> { {"Blog.Core",newstring[] { } }, }; c.AddSecurityRequirement(security); //方案名称“Blog.Core”可自定义,上下一致即可c.AddSecurityDefinition("Blog.Core",new ApiKeyScheme { Description ="JWT授权(数据将在请求头中进行传输) 直接在下框中输入{token}\"", Name ="Authorization",//jwt默认的参数名称In ="header",//jwt默认存放Authorization信息的位置(请求头中)Type ="apiKey" }); #endregion }); #endregion#regionToken服务注册 services.AddSingleton(factory => { varcache =newMemoryCache(new MemoryCacheOptions()); return cache; }); services.AddAuthorization(options => { options.AddPolicy("Client", policy => policy.RequireRole("Client").Build()); options.AddPolicy("Admin", policy => policy.RequireRole("Admin").Build()); options.AddPolicy("AdminOrClient", policy => policy.RequireRole("Admin,Client").Build()); }); #endregion }
然后执行代码,就可以看到效果
图 1
图 2
它的作用就是,每次请求时,从Header报文中,获取密钥token,这里根据token可以进一步判断相应的权限等。
接下来,就是在项目中添加五个文件,如下图
,图 3
具体来说:
1:JwtTokenAuth,一个中间件,用来过滤每一个http请求,就是每当一个用户发送请求的时候,都先走这一步,然后再去访问http请求的接口
public Task Invoke(HttpContext httpContext) { //检测是否包含'Authorization'请求头if(!httpContext.Request.Headers.ContainsKey("Authorization")) { return _next(httpContext); } vartokenHeader = httpContext.Request.Headers["Authorization"].ToString(); TokenModelJWT tm = JwtHelper.SerializeJWT(tokenHeader);//序列化token,获取授权 //授权varclaimList =newList(); varclaim =new Claim(ClaimTypes.Role, tm.Role); claimList.Add(claim); varidentity =new ClaimsIdentity(claimList); varprincipal =new ClaimsPrincipal(identity); httpContext.User = principal; return _next(httpContext); }
2:JwtHelper 一个帮助类,可以生成Token,和讲Token反序列成model
publicclass JwtHelper
{ publicstaticstringsecretKey {get;set; } ="sdfsdfsrty45634kkhllghtdgdfss345t678fs"; ////// 颁发JWT字符串 /////////publicstaticstring IssueJWT(TokenModelJWT tokenModel) { vardateTime = DateTime.UtcNow; varclaims =new Claim[] { newClaim(JwtRegisteredClaimNames.Jti,tokenModel.Uid.ToString()),//IdnewClaim("Role", tokenModel.Role),//角色new Claim(JwtRegisteredClaimNames.Iat,dateTime.ToString(),ClaimValueTypes.Integer64) }; //秘钥varkey =new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtHelper.secretKey)); varcreds =new SigningCredentials(key, SecurityAlgorithms.HmacSha256); varjwt =new JwtSecurityToken( issuer: "Blog.Core", claims: claims, //声明集合expires: dateTime.AddHours(2), signingCredentials: creds); varjwtHandler =new JwtSecurityTokenHandler(); varencodedJwt = jwtHandler.WriteToken(jwt); return encodedJwt; } ////// 解析 /////////publicstaticTokenModelJWT SerializeJWT(string jwtStr) { varjwtHandler =new JwtSecurityTokenHandler(); JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(jwtStr); objectrole =newobject(); ; try { jwtToken.Payload.TryGetValue("Role",out role); } catch (Exception e) { Console.WriteLine(e); throw; } vartm =new TokenModelJWT { Uid = (jwtToken.Id).ObjToInt(), Role = role !=null? role.ObjToString() :"", }; return tm; } }
3:定义中的TokenModelJWT,是一个令牌类,主要存储个人角色信息,自己简单写一个,也可以是你登陆的时候的用户信息,或者其他,
publicclass TokenModelJWT
{
////// Id
///publiclongUid {get;set; }
////// 角色
///publicstringRole {get;set; }
////// 职能
///publicstringWork {get;set; }
}
4:将四个文件都添加好后,最后两步
1、然后再Startup的Configure中,将TokenAuth注册中间件
2、在需要加权限的页面中,增加特性
这个时候,你运行项目,发现之前写的都报错了,
图 7
别慌!是因为每次操作请求,都会经过TokenAuth 中的Invoke方法,方法中对Header信息进行过滤,因为现在Header中,并没有相应的配置信息,看到这里,你就想到了,这个特别像我们常见的[HttpGet]等特性,没错!在.Net Core 中,到处都可以看到AOP编程,真的特别强大。
这个时候我们就用到了最开始的那个权限按钮
作者:SAYLINING
链接:https://www.jianshu.com/p/6d56d4f0ef8d