.NET Core 3.0 一个 jwt 的轻量角色/用户、单个API控制的授权认证库

640?wx_fmt=jpeg

作者:痴者工良(朋友合作原创)

来源:

https://www.cnblogs.com/whuanle/p/11743406.html

目录

  • 说明

  • 一、定义角色、API、用户

  • 二、添加自定义事件

  • 三、注入授权服务和中间件

  • 三、如何设置API的授权

  • 四、添加登录颁发 Token

  • 五、部分说明

  • 六、验证


说明

ASP.NET Core 3.0 一个 jwt 的轻量角色/用户、单个API控制的授权认证库

最近得空,重新做一个角色授权库,而之前做了一个角色授权库,是利用微软的默认接口做的,查阅了很多文档,因为理解不够,所以最终做出了有问题。

之前的旧版本 https://github.com/whuanle/CZGL.Auth/tree/1.0.0

如果要使用微软的默认接口,我个人认为过于繁杂,而且对于这部分的资料较少

使用默认接口实现授权认证,可以参考我另一篇文章

ASP.NET Core 使用 JWT 自定义角色/策略授权需要实现的接口

得益于大笨熊哥的引导,利用放假时间重新做了一个,利用微软本身的授权认证,在此基础上做拓展。特点是使用十分简便,无需过多配置;因为本身没有“造轮子”,所以如果需要改造,也十分简单。

此库更新到 .Net Core 3.0 了,如果需要在 2.2X 上使用,可以到仓库下载项目,然后把 Nuget 包换成 2.2 的。

项目仓库地址 https://github.com/whuanle/CZGL.Auth

一、定义角色、API、用户

随便新建一个网站或API项目,例如 MyAuth。

Nuget 里搜索 CZGL.Auth,按照 2.0.1 版本,或者使用 Package Manager 命令

Install-Package CZGL.Auth -Version 2.0.1

CZGL.Auth 设计思路是,网站可以存在多个角色、多个用户、多个API,

一个角色拥有一些 API,可以添加或删除角色或修改角色所有权访问的 API;

一个用户可以同时属于几个角色。

第一步要考虑网站的角色、用户、API设计,

CZGL.Auth 把这些信息存储到内存中,一个用户拥有那几个角色、一个角色具有哪些API的访问权限。

角色跟 API 是对应关系,用户跟角色是多对多关系。

新建一个类 RoleService.cs ,引入 using CZGL.Auth.Services;,RoleService 继承 ManaRole。

通过以下接口操作角色权限信息

  protected bool AddRole(RoleModel role);	protected bool AddUser(UserModel user);	protected bool RemoveRole(string roleName);	protected bool RemoveUser(string userName);

很明显,添加/移除一个角色,添加/移除一个用户

假如有 A、B、C 三个角色,有 /A、/B、/C、/AB、/AC、/BC、/ABC 共7个API,设定权限

A 可以访问 A、AB、AC、ABC

B 可以访问 B、AB、BC、ABC

C 可以访问 C、AC、BC、ABC

这里采用模拟数据的方法,不从数据库里面加载实际数据。

在 RoleService 里面增加一个方法

///<summary>	
/// 用于加载角色和API	
/// </summary>	
public void UpdateRole()	
{	List<RoleModel> roles = new List<RoleModel>	{	new RoleModel	{	RoleName="A",	Apis=new List<OneApiModel>	{	new OneApiModel	{	ApiName="A",	ApiUrl="/A"	},	new OneApiModel	{	ApiName="AB",	ApiUrl="/AB"	},	new OneApiModel	{	ApiName="AC",	ApiUrl="/AC"	},	new OneApiModel	{	ApiName="ABC",	ApiUrl="/ABC"	}	}	},	new RoleModel	{	RoleName="B",	Apis=new List<OneApiModel>	{	new OneApiModel	{	ApiName="B",	ApiUrl="/B"	},	new OneApiModel	{	ApiName="AB",	ApiUrl="/AB"	},	new OneApiModel	{	ApiName="BC",	ApiUrl="/BC"	},	new OneApiModel	{	ApiName="ABC",	ApiUrl="/ABC"	}	}	},	new RoleModel	{	RoleName="A",	Apis=new List<OneApiModel>	{	new OneApiModel	{	ApiName="A",	ApiUrl="/A"	},	new OneApiModel	{	ApiName="AB",	ApiUrl="/AB"	},	new OneApiModel	{	ApiName="AC",	ApiUrl="/AC"	},	new OneApiModel	{	ApiName="ABC",	ApiUrl="/ABC"	}	}	}	};	foreach (var item in roles)	{	AddRole(item);	}	}

有了角色和对应的API信息,就要添加用户了,

假设有 aa、bb、cc 三个用户,密码都是 123456,aa 属于 A 角色, bb 属于 B角色...

 public void UpdateUser()	
{	AddUser(new UserModel { UserName = "aa", BeRoles = new List<string> { "A" } });	AddUser(new UserModel { UserName = "bb", BeRoles = new List<string> { "B" } });	AddUser(new UserModel { UserName = "cc", BeRoles = new List<string> { "C" } });	
}

为了能够把角色和用户加载进 CZGL.Auth ,你需要在程序启动时,例如在 Program 里,使用

  RoleService roleService = new RoleService();	roleService.UpdateRole();	roleService.UpdateUser();

二、添加自定义事件

授权是,可能会有各种情况,你可以添加自定义事件记录下用户访问的授权信息、影响授权结果。

引用 using CZGL.Auth.Interface;

添加一个类 RoleEvents 继承 IRoleEventsHadner

public class RoleEvents : IRoleEventsHadner	
{	public async Task Start(HttpContext httpContext)	{	await Task.CompletedTask;	}	public void TokenEbnormal(object eventsInfo)	{	}	public void TokenIssued(object eventsInfo)	{	}	public void NoPermissions(object eventsInfo)	{	}	public void Success(object eventsInfo)	{	}	public async Task End(HttpContext httpContext)	{	await Task.CompletedTask;	}	
}

在 CZGL.Auth 开始验证授权前调用 Start,结束时调用 End,传入传参数是 HttpContext 类型,你可以在里面添加自定义授权的信息,在里面可以影响请求管道。

其他几个方法含义如下:

TokenEbnormal 客户端携带的 Token 不是有效的 Jwt 令牌,将不能被解析

TokenIssued 令牌解码后,issuer 或 audience不正确

NoPermissions 无权访问此 API

在授权认证的各个阶段将会调用上面的方法。

三、注入授权服务和中间件

使用 CZGL.Auth ,你需要注入以下两个服务

 services.AddRoleService(authOptions);	services.AddSingleton<IRoleEventsHadner, RoleEvents>();

AddRoleService 是注入授权服务,AddSingleton 注入你的事件。

AddRoleService 需要一个 AuthConfigModel 类型作参数。

你可以这样配置   

varauthOptions = new AuthBuilder()	
.Security("aaaafsfsfdrhdhrejtrjrt", "ASPNETCORE", "ASPNETCORE")	
.Jump("accoun/login", "account/error", false, false)	
.Time(TimeSpan.FromMinutes(20))	
.InfoScheme(new CZGL.Auth.Models.AuthenticateScheme	
{	TokenEbnormal = "Login authentication failed!",	TokenIssued = "Login authentication failed!",	NoPermissions = "Login authentication failed!"	
}).Build();	
services.AddRoleService(authOptions);	services.AddSingleton<IRoleEventsHadner, RoleEvents>();

Security 配置密钥相关,参数分别是密钥字符串、颁发者、订阅者。

Jump 配置授权失败时,跳转地址。参数分别是未授权时跳转、授权无效跳转,后面两个 bool 可以设置跳转或跳转。

Time 配置 Token 有效期。

InfoScheme 授权失败提示信息,例如

640?wx_fmt=png

上图的是时间过期的提示消息,用户请求API失败时返回 401 状态码,Header 会携带提示消息,CZGL.Auth 里面设置了三种情况下,自定义头部:

TokenEbnormal 客户端携带的 Token 不是有效的 Jwt 令牌,将不能被解析

TokenIssued 令牌解码后,issuer 或 audience不正确

NoPermissions 无权访问此 API

添加三个中间件

  app.UseAuthentication();	app.UseAuthorization();	app.UseMiddleware<RoleMiddleware>();

app.UseAuthorization();是微软授权认证的中间件,CZGL.Auth 会先让,默认的验证管道过滤一些无效请求和认证信息,再由 CZGL.Auth 来校验授权。


三、如何设置API的授权

很简单,CZGL.Auth 的认证授权,你只需在 Controller 或 Action上 添加 [Authorize]

CZGL.Auth 只会对使用了 [Authorize] 特性的 Controller 或 Action 生效。

如果一个 Controller 已经设置了 [Authorize] ,但是你想里面的 Action 跳过授权认证,则使用 [AllowAnonymous] 修饰 Action。

使用方法跟微软的默认的完全一致。这样无需过多配置。

如果你想另外定义一个特性用来另外设置 授权的话,可以到我的仓库提 Issue 或者直接联系我微信。

添加一个 APIController ,

 [Authorize]	[Route("api/[controller]")]	[ApiController]	public class TestController : ControllerBase	{	[HttpGet("/A")]	public JsonResult A()	{	return new JsonResult(new { Code = 200, Message = "Success!" });	}	[HttpGet("/B")]	public JsonResult B()	{	return new JsonResult(new { Code = 200, Message = "Success!" });	}	[HttpGet("/C")]	public JsonResult C()	{	return new JsonResult(new { Code = 200, Message = "Success!" });	}	[HttpGet("/AB")]	public JsonResult AB()	{	return new JsonResult(new { Code = 200, Message = "Success!" });	}	[HttpGet("/BC")]	public JsonResult BC()	{	return new JsonResult(new { Code = 200, Message = "Success!" });	}	[HttpGet("/AC")]	public JsonResult AC()	{	return new JsonResult(new { Code = 200, Message = "Success!" });	}	[HttpGet("/ABC")]	public JsonResult ABC()	{	return new JsonResult(new { claims = User.Claims });	}	/// <summary>	/// 任何人都不能访问	/// </summary>	/// <returns></returns>	[HttpGet("D")]	public JsonResult D()	{	return new JsonResult(new { Code = 200, Message = "Success!" });	}	[HttpGet("error")]	public JsonResult Denied()	{	return new JsonResult(	new	{	Code = 0,	Message = "访问失败!",	Data = "此账号无权访问!"	});	}	}

四、添加登录颁发 Token

添加一个 AccountController.cs 用来颁发登录、 Token。

[Route("api/[controller]")]	
[ApiController]	
public class AccountController : ControllerBase	
{	[HttpPost("/Login")]	public async Task<JsonResult> Login([FromQuery]string username, string password, string rolename)	{	// 用户名密码是否正确	if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password) || string.IsNullOrWhiteSpace(rolename))	{	return new JsonResult(new	{	Code = 0,	Message = "尼玛,上传什么垃圾信息",	});	}	if(!((username=="aa"||username=="bb"||username=="cc")&&password=="123456"))	{	return new JsonResult(new	{	Code = 0,	Message = "账号或密码错误",	});	}	// 你自己定义的角色/用户信息服务	RoleService roleService = new RoleService();	// 检验用户是否属于此角色	var role = roleService.IsUserToRole(username,rolename);	// CZGL.Auth 中一个用于加密解密的类	EncryptionHash hash = new EncryptionHash();	// 设置用户标识	var userClaims = hash.BuildClaims(username, rolename);	自定义构建配置用户标识	/// 自定义的话,至少包含如下标识	//var userClaims = new Claim[]	//{	//new Claim(ClaimTypes.Name, userName),	//    new Claim(ClaimTypes.Role, roleName),	//    new Claim(JwtRegisteredClaimNames.Aud, Audience),	//    new Claim(ClaimTypes.Expiration, TimeSpan.TotalSeconds.ToString()),	//    new Claim(JwtRegisteredClaimNames.Iat, new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds().ToString())	//};	/*	iss (issuer):签发人	exp (expiration time):过期时间	sub (subject):主题	aud (audience):受众	nbf (Not Before):生效时间	iat (Issued At):签发时间	jti (JWT ID):编号	*/	// 方法一,直接颁发 Token	ResponseToken token = hash.BuildToken(userClaims);	//方法二,拆分多步,颁发 token,方便调试	//var identity = hash.GetIdentity(userClaims);	//var jwt = hash.BuildJwtToken(userClaims);	//var token = hash.BuildJwtResponseToken(jwt);	return new JsonResult(token);	}	
}

五、部分说明

注入 Jwt 服务、颁发 Token

CZGL.Auth 把使用 jwt 的服务和颁发 Token 的代码封装好了,这个库不是在“造轮子”,所以实际上你可以很轻松的把这部分的代码抽出来,另外设计。

这部分的代码所在位置 RoleServiceExtension.cs 、EncryptionHash.cs。

授权中间件

  app.UseAuthentication();	app.UseAuthorization();	app.UseMiddleware<RoleMiddleware>();

我的写法是利用 ASP.NET Core 的 jwt 完成基础的认证授权,然后在下一个管道中实现拓展的认证。但是本身的认证是在 app.UseAuthorization(); 做了拓展,所以使用 CZGL.Auth,只需要按照平常 jwt 的方式去使用,只是加了一个 RoleMiddleware 中间件。

CZGL.Auth 只是我受到新思路启发临时写出来的。。。最好不要直接用于生产,去 github 库把项目下载下来,按照自己应用场景改一下~。


六、验证

先使用 aa 用户登录,登录时选择 A 角色。

640?wx_fmt=png

因为 A 用户只能访问 “带有 A ” 的API, "/A"、"/AB" 等,所以我们可以试试。

640?wx_fmt=png

继续用这个 Token 访问一下 "/B"

640?wx_fmt=png

可以继续尝试添加 API 或者使用其他用户登录,访问不同的 API。

由于别人对前端不熟,所以就不写带页面的示例了~。

可以用 Postman 就行测试。

什么示例的 项目可以到仓库里下载,名称是 MyAuth。

一般上,用户权限、角色权限信息是存储在数据库里面的,另一个示例是 CZGL.Auth.Sample2。

这个库只是较为粗略的授权认证,与更丰富的需求请自行下载源码修改~

640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/313204.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.NET Core 3.0 构建和部署

Default Executables 默认可执行文件 在 dotnet build 或 dotnet publish 期间&#xff0c;将创建一个与你使用的 SDK 的环境和平台相匹配的可执行文件。 和其他本机可执行文件一样&#xff0c;可以使用这些可执行文件执行相同操作&#xff0c;例如&#xff1a; 可以双击可执行…

为什么我会了SOA,你们还要逼我学微服务?

菜菜哥&#xff0c;我最近需要做一个项目&#xff0c;老大让我用微服务的方式来做那挺好呀&#xff0c;微服务现在的确很流行我以前在别的公司都是以SOA的方式&#xff0c;SOA也是面向服务的方式呀的确&#xff0c;微服务和SOA有相同之处面向服务的架构&#xff08;SOA&#xf…

面对万物互联的智能世界,你是否也想分一杯羹

第六届世界互联网大会于10月20日至22日在浙江乌镇顺利举行。作为世界互联网大会“13”架构的重要组成部分&#xff0c;“互联网之光”博览会以“智能互联网、开放合作——携手共建网络空间命运共同体”为主题&#xff0c;集中展示了全球范围内的互联网新技术、新成果、新产品、…

你必须知道的容器监控 (2) cAdvisor

# 实验环境&#xff1a;阿里云ECS主机&#xff08;两台&#xff09;&#xff0c;CentOS 7.401—cAdvisor简介为了解决容器的监控问题&#xff0c;Google开发了一款容器监控工具cAdvisor&#xff08;Container Advisor&#xff09;&#xff0c;它为容器用户提供了对其运行容器的…

代码阅读

http://alanse7en.github.io/caffedai-ma-jie-xi-4/ 三. 从一个比较宏观的层面上去了解caffe怎么去完成一些初始化的工作和使用Solver的接口函数&#xff0c;本文将主要分为四部分的内容&#xff1a; Google Flags的使用Register Brew Function的宏的定义和使用train()函数的…

动手造轮子:实现一个简单的依赖注入(一)

动手造轮子&#xff1a;实现一个简单的依赖注入(一)Intro在上一篇文章中主要介绍了一下要做的依赖注入的整体设计和大概编程体验&#xff0c;这篇文章要开始写代码了&#xff0c;开始实现自己的依赖注入框架。类图首先来温习一下上次提到的类图服务生命周期服务生命周期定义&am…

Qt 调试Caffe

http://blog.csdn.net/xg123321123/article/details/52817658 1.下载并安装Qt Creator 下载页面&#xff0c;推荐使用4.x版本&#xff0c;比如&#xff1a; Qt Creator 4.1.0 for Linux 64-bit下载的是run包&#xff0c;安装方法&#xff1a; cd到下载目录 chmod x xxx.run …

.NET Core 3.0 本地工具

.NET Core从最早期的版本就开始支持全局工具了。如果仅仅需要在某个项目中或某个文件夹中使用特定的工具&#xff0c;那么.NET Core 3.0就允许您这样做。 使用.NET Core 3.0&#xff0c;您可以在特定的文件夹下安装“本地”工具&#xff0c;它的作用范围仅限于该文件夹及其子文…

Nsight 调试 Caffe

http://blog.csdn.net/u014114990/article/details/47723877 右键属性菜单的General->Code Analysis->Paths and Symbols下进行加入&#xff1a; Includes下加入程序需要用到的头文件的路径&#xff1a; Library Path下添加需要用到库文件的路径&#xff1a; 具体用到的…

张高兴的 .NET Core IoT 入门指南:(五)PWM 信号输出

什么是 PWM在解释 PWM 之前首先来了解一下电路中信号的概念&#xff0c;其中包括模拟信号和数字信号。模拟信号是一种连续的信号&#xff0c;与连续函数类似&#xff0c;在图形上表现为一条不间断的连续曲线。数字信号为只能取有限个数值的信号&#xff0c;比如计算机中的高电平…

.NET Core 3 对 IoT 应用程序的高级支持:System.Device.Gpio

System.Device.Gpio 是一个全新的 .Net Core 开源库&#xff0c;它旨在使 IoT&#xff08;物联网&#xff09;应用程序能够通过其 GPIO 引脚或其他 I/O 控制硬件与传感器、显示器和输入设备进行交互。该库是由社区维护的多个设备绑定集合来进行增强实现的。正如微软 .NET 项目…

代码阅读2

http://blog.csdn.net/u014568921/article/details/53995455 首先&#xff0c;要知道caffe里的卷积核都是三维的 在caffe中卷积核是三维的还是二维的&#xff1f; 下面分割线之间的内容来自http://blog.csdn.NET/u014114990/article/details/51125776 /*********************…

一文带你了解华为云DevCloud为何能全面领跑中国DevOps云服务市场

近日&#xff0c;国际权威调研机构IDC发布了《IDC MarketScape&#xff1a;中国DevOps云服务市场2019厂商评估》报告&#xff0c;该报告从战略和能力两个维度对国内主流DevOps云厂商进行了评估&#xff0c;报告显示&#xff0c;华为云位于 IDC MarketScape “中国DevOps云服务 …

[电子书制作]Excel催化剂输出内容汇总PDF及Word版本分享

Excel催化剂在2018年开始&#xff0c;陆续写出了230篇高质量原创性文章&#xff0c;将Excel催化剂插件的开发过程及使用方法全方位地通过文字的方式给广大网友们分享了。电子书下载方式同样地&#xff0c;为了减少大家过多繁琐的资料下载途径&#xff0c;电子书的下载路径和之前…

深入理解.NET Core的基元: deps.json, runtimeconfig.json, dll文件

原文链接&#xff1a; Deep-dive into .NET Core primitives: deps.json, runtimeconfig.json, and dlls作者&#xff1a; Nate McMasterC#编译器(The C# Compiler)C#的编译器可以将cs文件转换为dll文件, 即程序集文件。程序集文件是一个便携的可执行格式文件, 借助.NET Core,它…

C# 8.0 的默认接口方法

例子直接看例子有这样一个接口&#xff1a; 然后有三个它的实现类&#xff1a; 然后在main方法里面调用&#xff1a; 截至目前&#xff0c;程序都可以成功的编译和运行。 IPerson接口变更 突然&#xff0c;我想对所有的人类添加一个新的特性&#xff0c;例如&#xff0c;添加一…

convolutional layer 源代码

http://blog.csdn.net/xizero00/article/details/51049858 一、 卷积层的作用简介 卷积层是深度神经网络中的一个重要的层&#xff0c;该层实现了局部感受野&#xff0c;通过这种局部感受野&#xff0c;可以有效地降低参数的数目。我们将结合caffe来讲解具体是如何实现卷积层的…

在.net core3.0中使用SignalR实现实时通信

最近用.net core3.0重构网站&#xff0c;老大想做个站内信功能&#xff0c;就是有些耗时的后台任务的结果需要推送给用户。一开始我想简单点&#xff0c;客户端每隔1分钟调用一下我的接口&#xff0c;看看是不是有新消息&#xff0c;有的话就告诉用户有新推送&#xff0c;但老大…

活动最后72小时:购书优惠劵,折后再折,赶紧来抢啊

1024程序员节当当网计算机图书每满100减50&#xff01;满200减100&#xff01;满300-150&#xff01;机械工业出版社华章公司联合当当网特意为【DotNET技术圈】用户申请了一批可与满减叠加使用的“满200减30”的图书优惠码&#xff0c;优惠码使用后相当于&#xff1a;400减230 …