Core + Vue 后台管理基础框架3——后端授权
1、前言
但凡业务系统,授权是绕不开的一环。见过太多只在前端做菜单及按钮显隐控制,但后端裸奔的,觉着前端看不到,系统就安全,掩耳盗铃也好,自欺欺人也罢,这里不做评论。在.NET CORE中,也见过不少用操作过滤器来实现业务用例权限控制的,至少算是对后端做了权限控制。
但我们知道,操作过滤器,已经算是过滤器管道中最靠后的,基本上紧挨着我们控制器方法执行那里了,本身,操作过滤器也不是做权限控制的地方,虽然本身它能达到权限控制效果。为什么这么说,试想下,在过滤器管道之前,还有中间件处理管道,即便是过滤器管道执行环节,操作过滤器也是最靠后的,它往前还有授权过滤器,资源过滤器等,假如我在资源过滤器中缓存了请求结果,那权限控制基本上就废了。
说这么多,只想表达一点,合适的地方,合适的东西,干合适的事儿。在.NET CORE中,官方推荐用策略去实现授权。策略授权,是在授权中间件环节执行,当然能解决上述执行流程先后顺序的问题。但如果要直接应用于我们业务系统中的权限控制,恐怕远远不够,因为你不可能为每个api用例创建一个角色或策略,更主要的,权限控制还要动态授予或回收的,不做扩展直接照搬,你是很难搞的。接下来,我们就来看看,如何基于core的授权机制,去实现我们传统的用户,角色,权限,及权限的动态授予与回收控制。
2、实现
我们先看看,菜单表概览:

查询中IsMenu代表是侧边栏菜单还是功能按钮,这里我把按钮级别的给筛选出来了,每个按钮菜单都代表一个业务用例,也对应我们一个控制器方法。 Code是唯一的,待会儿权限控制标识,会采用这个字段。当然你用主键ID也可以,但比较难记。实际运维中,会把这些菜单按照业务分配给指定角色,再把指定角色分配给系统用户。
接下来,定义一个Requirement,以权限码作为主校验对象:
public class PermissionRequirement : IAuthorizationRequirement
{
public PermissionRequirement(params string[] codes)
{
this.Codes = codes;
} public string[] Codes { get; private set; }
}
有Requirement,自然有RequirementHandler:
public class PermissionHandler : AuthorizationHandler<PermissionRequirement>
{
private readonly IMenuService _menuService; public PermissionHandler(IMenuService menuService)
{
_menuService = menuService;
} protected override async Task HandleRequirementAsync(
AuthorizationHandlerContext context,
PermissionRequirement requirement)
{
var roles = context.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Role).Value;
if (!string.IsNullOrWhiteSpace(roles))
{
var roleIds = roles.Split(',', StringSplitOptions.RemoveEmptyEntries)
.Select(x => long.Parse(x));
if (roleIds.Contains())
{
context.Succeed(requirement);
return;
} var menus = await _menuService.GetMenusByRoleIds(roleIds.ToArray());
if (menus.Any())
{
var codes = menus.Select(x => x.Code.ToUpper());
if (requirement.Codes.Any(x => codes.Contains(x.ToUpper())))
{
context.Succeed(requirement);
}
}
}
}
}
逻辑比较常规,根据当前用户角色,获取其所有菜单权限,然后与Requirement中声明要求的菜单权限做对比,如果含有,则放行。到这儿,大家应该都能看懂,典型的.NET CORE权限控制组件。
接下来,定义一个授权过滤器特性:
public class PermissionFilter : Attribute, IAsyncAuthorizationFilter
{
private readonly IAuthorizationService _authorizationService;
private readonly PermissionRequirement _requirement; public PermissionFilter(IAuthorizationService authorizationService, PermissionRequirement requirement)
{
_authorizationService = authorizationService;
_requirement = requirement;
} public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
var result = await _authorizationService.AuthorizeAsync(context.HttpContext.User, null, _requirement); if (!result.Succeeded)
{
context.Result = new JsonResult("您没有此操作权限")
{
StatusCode = (int)HttpStatusCode.Forbidden
};
}
}
}
从这儿开始,我估计有人就要看不懂了,下边解释下。首先,PermissionFilter是个授权过滤器,它实现了IAsyncAuthorizationFilter,所以会作为过滤器管道第一道去执行。构造函数中有2个参数,IAuthorizationService直接注入,PermissionRequirement则通过特性标记外部设置。在OnAuthorizationAsync重写方法中,调用IAuthorizationService.AuthorizeAsync方法去做具体授权校验工作,经此桥接,授权流程就转到我们最开始定义的PermissionHandler去了。本身core源码中,IAuthorizationService是在授权中间件中使用到的,这里我借用了。注意,一旦过滤器注入了服务,那此过滤器便不再能够直接以打标记的形式贴在控制器或方法上了,那种形式必须所有参数都直接指定。core中给出的方案,是TypeFilter,涉及到服务注入的时候。
那接下来,就是另一个重要对象了:
/// <summary>
/// 权限特性
/// </summary>
public class PermissionAttribute : TypeFilterAttribute
{
public PermissionAttribute(params string[] codes)
: base(typeof(PermissionFilter))
{
Arguments = new[] { new PermissionRequirement(codes) };
}
}
至此,各组件定义完毕,那我们使用就类似下边这样:

3、效果演示
guokun用户角色:

网站管理员角色对应权限:

可以看到,是没有勾选删除部门的,那我们用这个账户来删除下部门:

状态码403,并提示无权操作,删除动作已经被拦截了。那我们把删除权限赋予网站管理员:

接下来再来删除:

可以看到,已经删除部门成功。
3、总结
以上便是本项目权限控制的实现。认证&授权这块儿,如果要做好,还是得把core的整套机制弄清楚,最好能把源码过一遍,不然根本搞不清楚需要怎么扩展,每个扩展点在什么时机触发及生效。
Core + Vue 后台管理基础框架3——后端授权的更多相关文章
- Core + Vue 后台管理基础框架4——前端授权
1.前言 上篇,我们讲了后端的授权.与后端不同,前端主要是通过功能入口如菜单.按钮的显隐来控制授权的.具体来讲,就是根据指定用户的制定权限来加载对应侧边栏菜单和页面内的功能按钮.我们一个个来讲. 2. ...
- Core + Vue 后台管理基础框架0——开篇
1.背景 最近,打算新开个项目,鉴于团队技术栈,选型.net core + vue,前后端分离.本打算捡现成的轮子的,github上大致逛了逛,总发现这样那样的不太适合心中那些“完美实践”,例如:Ab ...
- Core + Vue 后台管理基础框架2——认证
1.前言 这块儿当时在IdentityServer4和JWT之间犹豫了一下,后来考虑到现状,出于3个原因,暂时放弃了IdentityServer4选择了JWT: (1)目前这个前端框架更适配JWT: ...
- Core + Vue 后台管理基础框架1——运行系统
1.down源码 git clone https://github.com/KINGGUOKUN/SystemManagement.git,项目目录如下: 2.还原数据库 找到项目根目录下System ...
- Core + Vue 后台管理基础框架8——Swagger文档
1.前言 作为前后端分离的项目,或者说但凡涉及到对外服务的后端,一个自描述,跟代码实时同步的文档是极其重要的.说到这儿,想起了几年前在XX速运,每天写完代码,还要给APP团队更新文档的惨痛经历.给人家 ...
- Core + Vue 后台管理基础框架9——统一日志
1.背景 前阵子有园友留言,提到日志相关的东西,同时,最近圈子里也有提到日志这个东西.一个充分.集中的统一日志平台还是很有必要的,否则系统出问题了只能靠猜或者干瞪眼.何谓充分,日志记录满足最低要求.出 ...
- Core + Vue 后台管理基础框架7——APM
1.前言 APM,又称应用性能统计,主要用来跟踪请求调用链,每个环节调用耗时,为我们诊断系统性能.定位系统问题提供了极大便利.本系统采用的是Elastic Stack体系中的APM,主要是之前部门搞P ...
- hsweb 企业后台管理基础框架
hsweb 详细介绍 业务功能 现在: 权限管理: 权限资源-角色-用户. 配置管理: kv结构,自定义配置.可通过此功能配置数据字典. 脚本管理: 动态脚本,支持javascript,groovy, ...
- 基于bootstrap的漂亮网站后台管理界面框架汇总
基于bootstrap的漂亮网站后台管理界面框架汇总 10个最新的 Bootstrap 3 管理模板 这里分享的 10 个模板是从最新的 Bootstrap 3 管理模板集合中挑选出来的,可以帮助你用 ...
随机推荐
- 收集到的技术相关网址——python
1.Python中常用数据库访问接口模块 专用数据库连接模块——MySQL.SQLite.PostgreSQL.Oracle.IBM DB2.Infomix.Interbase.Sybase.SQL ...
- http、https的压测工具——apacheab 、webbench
http的压测工具 搞清楚不同的安装方法,执行文件.配置文件的路径. yum安装: 执行文件在/usr/bin 下,一般为执行文件 配置文件在/etc目录下 conf文件 源码安装: 执行文件在安装文 ...
- c语言函数指针的理解与使用(学习)
1.函数指针的定义 顾名思义,函数指针就是函数的指针.它是一个指针,指向一个函数.看例子: 1 2 3 A) char * (*fun1)(char * p1,char * p2); B) char ...
- 吴裕雄--天生自然python学习笔记:Python3 迭代器与生成器
迭代器 迭代是Python最强大的功能之一,是访问集合元素的一种方式. 迭代器是一个可以记住遍历的位置的对象. 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退 ...
- 提升项目一:花卉管理系统(Servlet+JSP完成)
这个是写的第一个项目:使用Servlet+JSP完成,加上对底层构架的理解,才可以对后面要接触使用的ssh框架的深刻理解 2017-02-11: 完成对进货业务的操作, 下一步完成对销货业务的操作
- 《自动化平台测试开发-Python测试开发实战》新书出版了
首先 第一本书,当初在百度阅读初步写了个电子版,刚一上线不久即收到了数百位读者朋友阅读收藏购买,于是顺利成章就出版了纸质书. <软件自动化测试开发>认真看过的读者应该都知道,介绍的主要是自 ...
- <HAOI2008>硬币购物
和神奇dp的战斗 还有容斥原理 终于get到了 #include<cstdio> #include<cstring> #include<iostream> #inc ...
- 吴裕雄--天生自然 R语言数据分析:火箭发射的地点、日期/时间和结果分析
dfS = read.csv("F:\\kaggleDataSet\\spacex-missions\\database.csv") library(dplyr) library( ...
- Python 代码实现验证码识别
Python 代码实现验证码识别 测试开发社区 1周前 源 / j_hao104 一.探讨 识别图形验证码可以说是做爬虫的必修课,涉及到计算机图形学,机器学习,机器视觉,人工智能等等高深领域…… ...
- golang xml解析
第二章里还提到了xml的解析部分.之前有想整理下encoding包下常用的几个文件格式的处理.这次刚好整理下xml的部分.先上例子 1 2 3 4 5 6 7 8 9 10 11 12 13 14 1 ...