一、前言

实际上权限系统老早之前我就在一直开发,大概在刚毕业没多久就想一个人写一个系统,断断续续一直坚持到现在,毕竟自己亲动手自写的系统才有收获,本篇仅介绍权限。

  小小系统上不了台面,望各位大神勿喷。

二、系统介绍

目前采用的是.Net Core微服务的方式实现,本文不讨论具体的中间件主要是(ocelot + consul等),一直参考微软的  eShopOnContainers ,进行简单的实现,但是ORM是用的Dapper,并简单进行封装  传送门 ,当然自己也封装了一些简单的插件进行复用:传送门,如下:

三、权限系统

权限系统实现很简单,权限的划分我觉得可以分为三种:

1、菜单权限2、按钮权限3、数据权限

简单介绍下:1、菜单权限。表示用户是否能够访问该页面(角色挂钩)

      2、按钮权限。表示用户是否能够操作该页面上的功能(角色挂钩)

      3、数据权限。表示用户访问页面时进行数据筛选(该功能暂未实现,这个要与具体的业务结合才能写),与部门挂钩,这个不太好理解,当然一般的权限系统这个功能也不会做,举个简单例子,OA系统里面我查看我的工资条,我应该只能看到我自己的数据,但是我的部门经理,他可以有权限看到该部门的全部数据,这个就是数据权限。

为什么写这个系统?

  之前待过好几家公司,发现他们的系统都是对菜单进行分配,当然了,业务需求只要这个就当我没说,我只是觉得这样做太不安全并且我觉得之前系统的实现方式可以进行一些优化,所以就一直写到现在,可能代码质量不如哪些大神的优秀,系统在我看来太小,就简单搭了个框架实现。你过条小水沟,没必要造条桥。

要使用该系统前提条件:前端:Sea.js和Vue,对于sea.js,在前端这块感觉已经没多少人用了,但是这中CMD思想是不会被淘汰的,你看最近比较火的layerui也是的,对于Vues只是简单的应用,也就用到双向绑定而已,开发复杂的页面确实比较方便,但是简单的页面就得不偿失了。

           后端:consul、rabbitmq ,具体怎么安装不在描述

大概的用户访问流程描述如下:

用户登录      =====》  获取该用户角色   ===》  通过角色获取该角色对应的权限 并集  ===>返回相应数据

      sys_user_role      sys_role_resource

系统关系图如下(MySQL):

具体功能实现请看代码,这里不做阐述,菜单权限的分配通过角色表和菜单表的关联表操作即可,但是按钮的权限分配如何实现?我的实现方式是:把按钮的操作也看成一种菜单的资源分配,只不过比较特殊,我这里不仅仅是对按钮的显示进行控制,我做的比较绝,也对后台方法访问权限也做了控制,这样比较安全,对于按钮权限的控制,实际上是明确的,比方说,一个删除按钮,它只能对应后台的一个删除方法,这个方法是明确的,对于页面的按钮的类型和个数是固定的,不然你没办法分配,基于这个前提,我对菜单的生成进行代码控制从而达到控制目的,因此,菜单和按钮和在一起称之为资源表 sys_resource 。具体的实现代码也不是很复杂,一层一层判断即可,权限过滤器如下:

  1     public class PermissionAuthorizationRequirement : IAuthorizationRequirement
  2     {
  3         public UrlAndButtonType UrlAndButtonType { get; }
  4
  5         public PermissionAuthorizationRequirement(string url, ButtonType buttonType, bool isPage)
  6         {
  7             UrlAndButtonType = new UrlAndButtonType()
  8             {
  9                 Url = url,
 10                 ButtonType = (byte)buttonType,
 11                 IsPage = isPage
 12             };
 13         }
 14         public PermissionAuthorizationRequirement(string url, byte buttonType, bool isPage)
 15         {
 16             UrlAndButtonType = new UrlAndButtonType()
 17             {
 18                 Url = url,
 19                 ButtonType = buttonType,
 20                 IsPage = isPage
 21             };
 22         }
 23     }
 24     /// <summary>
 25     /// 权限过滤器
 26     /// </summary>
 27     [Authorize]
 28     [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
 29     public sealed class PermissionAttribute : TypeFilterAttribute
 30     {
 31         /// <summary>
 32         /// 构造器
 33         /// </summary>
 34         /// <param name="url">地址</param>
 35         /// <param name="buttonType">按钮类型</param>
 36         /// <param name="isPage">是否是页面</param>
 37         public PermissionAttribute(string url = default(string), ButtonType buttonType = ButtonType.View, bool isPage = true) :
 38             base(typeof(RequiresPermissionAttributeExecutor))
 39         {
 40             Arguments = new object[] { new PermissionAuthorizationRequirement(url, buttonType, isPage) };
 41         }
 42         /// <summary>
 43         /// 构造器
 44         /// </summary>
 45         /// <param name="url">地址</param>
 46         /// <param name="buttonType">按钮类型</param>
 47         /// <param name="isPage">是否是页面</param>
 48         public PermissionAttribute(string url, byte buttonType, bool isPage = true) :
 49             base(typeof(RequiresPermissionAttributeExecutor))
 50         {
 51             Arguments = new object[] { new PermissionAuthorizationRequirement(url, buttonType, isPage) };
 52         }
 53
 54         private class RequiresPermissionAttributeExecutor : Attribute, IAsyncResourceFilter
 55         {
 56             private IPermissionStorageContainer _permissionStorage;
 57             private PermissionAuthorizationRequirement _requiredPermissions;
 58
 59             public RequiresPermissionAttributeExecutor(
 60                 IPermissionStorageContainer permissionStorage, PermissionAuthorizationRequirement requiredPermissions)
 61             {
 62                 _permissionStorage = permissionStorage;
 63                 _requiredPermissions = requiredPermissions;
 64             }
 65
 66             public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
 67             {
 68                 string menuUrl = _requiredPermissions.UrlAndButtonType.Url;
 69                 //判断用户权限
 70                 if (string.IsNullOrEmpty(menuUrl))
 71                 {
 72                     //区域判断
 73                     string area = context.RouteData.Values["area"].ToString();
 74                     if (string.IsNullOrEmpty(area))
 75                     {
 76                         menuUrl = "/" + context.RouteData.Values["controller"] + "/" + context.RouteData.Values["action"];
 77                     }
 78                     else
 79                     {
 80                         menuUrl = "/" + area + "/" + context.RouteData.Values["controller"] + "/" + context.RouteData.Values["action"];
 81                     }
 82                 }
 83                 menuUrl = menuUrl.Trim().ToLower();
 84                 var dbpermission = await _permissionStorage.GetPermissionAsync();
 85                 var menu = dbpermission.Menus.FirstOrDefault(m => m.MenuUrl != null && m.MenuUrl.Trim().ToLower() == menuUrl);
 86                 if (menu != null)//地址存在
 87                 {
 88                     if (_requiredPermissions.UrlAndButtonType.ButtonType == default(byte))
 89                     {
 90                         await next();
 91                     }
 92                     else
 93                     {
 94                         byte buttonType = (byte)_requiredPermissions.UrlAndButtonType.ButtonType;
 95                         if (menu.MenuButton.Select(m => m.ButtonType).Contains(buttonType))//拥有操作权限
 96                         {
 97                             await next();
 98                         }
 99                         else
100                         {
101                             //没有操作权限
102                             if (_requiredPermissions.UrlAndButtonType.IsPage)
103                             {
104                                 context.Result = new RedirectResult("/error/noauth");
105                             }
106                             else
107                             {
108                                 context.Result = new ContentResult()
109                                 {
110                                     Content = PermissionStatusCodes.Status2Unauthorized.ToString()
111                                 };
112                             }
113                             await context.Result.ExecuteResultAsync(context);
114                         }
115                     }
116                 }
117                 else
118                 {
119                     //没有操作权限
120                     if (_requiredPermissions.UrlAndButtonType.IsPage)
121                     {
122                         context.Result = new RedirectResult("/error/noauth");
123                     }
124                     else
125                     {
126                         context.Result = new ContentResult()
127                         {
128                             Content = PermissionStatusCodes.Status2Unauthorized.ToString()
129                         };
130                     }
131                     await context.Result.ExecuteResultAsync(context);
132                 }
133             }
134         }
135
136     }

在对于的页面添加过滤器即可,如下:

 1         [HttpGet]
 2         [Permission]
 3         public async Task<IActionResult> Index(int pageIndex=1,int pageSize=10)
 4         {
 5             var res = await _messageService.GetPageAsync(pageIndex, pageSize);
 6             return View(res);
 7         }
 8         [HttpGet]
 9         [Permission("/Sys/Message/Index", ButtonType.View)]
10         public IActionResult Show()
11         {
12             return View();
13         }

系统界面展示图:后台模板是之前从网上找的并自己简单改了一下,将就能看吧,实在不想花功夫在前端上面了@-^-@

运行步骤:1、确保数据库mssystem和mssystemlog存在 github文档中

     2、consul服务启动,如下回车运行

     3、VS项目启动

管理员登录账号wms,密码:所有账号密码都是123

代码地址:

https://github.com/wangmaosheng/MsSystem-BPM-ServiceAndWebApps

如果觉得有点作用的话,可以 start 下,后续会持续更新

转载于:https://www.cnblogs.com/wms01/p/10903646.html

.NET Core微服务 权限系统+工作流(一)权限系统相关推荐

  1. .NET Core微服务 权限系统+工作流(二)工作流系统

    一.前言 接上一篇 .NET Core微服务 权限系统+工作流(一)权限系统 ,再来一发 工作流,我在接触这块开发的时候一直好奇它的实现方式,翻看各种工作流引擎代码,探究其实现方式,个人总结出来一个核 ...

  2. NET Core微服务之路:实战SkyWalking+Exceptionless体验生产下追踪系统

    前言 当一个APM或一个日志中心实际部署在生产环境中时,是有点力不从心的. 比如如下场景分析的问题: 从APM上说,知道某个节点出现异常,或延迟过过高,却不能及时知道日志反馈情况,总不可能去相应的节点 ...

  3. 【NET CORE微服务一条龙应用】第三章 认证授权与动态权限配置

    [NET CORE微服务一条龙应用]第三章 认证授权与动态权限配置 介绍 系列目录:[NET CORE微服务一条龙应用]开始篇与目录 在微服务的应用中,统一的认证授权是必不可少的组件,本文将介绍微服务 ...

  4. .NET Core微服务之基于Ocelot+IdentityServer实现统一验证与授权

    Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.案例结构总览 这里,假设我们有两个客户端(一个Web网站,一个移动App),他们要使用系统,需要通过API网关(这里API网关始终作为 ...

  5. .NET Core微服务系列基础文章索引(目录导航Final版)

    一.为啥要总结和收集这个系列? 今年从原来的Team里面被抽出来加入了新的Team,开始做Java微服务的开发工作,接触了Spring Boot, Spring Cloud等技术栈,对微服务这种架构有 ...

  6. ABP vNext微服务架构详细教程——分布式权限框架(上)

    1 简介 ABP vNext框架本身提供了一套权限框架,其功能非常丰富,具体可参考官方文档:https://docs.abp.io/en/abp/latest/Authorization 但是我们使用 ...

  7. .NET Core微服务开发选项

    微服务开发的关注点有哪些? 微服务构最终的目标是实现业务的价值,交付,为了让开发人员更加关注业务开发和交付,微服务需要一些比较底层的基础设置,我们也称为微服务公共关注点. 配置管理:对微服务可变参数进 ...

  8. .Net Core微服务架构技术栈的那些事

    一.前言 大家一直都在谈论微服务架构,园子里面也有很多关于微服务的文章,前几天也有一些园子的朋友问我微服务架构的一些技术,我这里就整理了微服务架构的技术栈路线图,这里就分享出来和大家一起探讨学习,同时 ...

  9. .NET Core微服务之路:基于Ocelot的API网关实现--http/https协议篇

    前言 最近一直在忙公司和私下的兼职,白天十个小时,晚上四个小时,感觉每天都是打了鸡血似的,精神满满的,连自己那已经学打酱油的娃都很少关心,也有很长一段时间没有更新博客了,特别抱歉,小伙伴们都等得想取关 ...

最新文章

  1. vmware虚拟机启动centOs黑屏
  2. android studio导出apk_Android 应用构建速度提升的十个小技巧
  3. .NET Conf 2019 今天在上海开幕,图片直播地址
  4. java 可重入读写锁 ReentrantReadWriteLock 详解
  5. aop统计请求数量_Spring-Boot+AOP+统计单次请求方法的执行次数和耗时情况-Go语言中文社区...
  6. Java工作笔记-生成及解析Json字符串
  7. Java NIO学习篇之缓冲区ByteBuffer详解
  8. P2525 Uim的情人节礼物·其之壱 【字典序】【STL:prev_permutation】
  9. python实现栅栏密码加解密
  10. 生物信息学常用软件—2(PCR引物设计及相关软件使用)
  11. 1209 实验三同学评论
  12. Curious Cupid
  13. 大流量下订单号生成方法
  14. configure error:Package requirements (openssl) were not met
  15. 项目实战:Qt贝塞尔曲线拽托顶点实时显示工具
  16. 递归函数--猴子摘桃问题的解题思路
  17. matlab双纵坐标的绘图命令_[转载]MATLAB画双纵坐标 plotyy的用法 对数坐标
  18. 宇宙最强vscode教程
  19. 面经分享 | 2年经验,1个月拿下阿里P6 Offer
  20. matlab均值、方差函数

热门文章

  1. ArcGIS Engine基础开发教程(转)
  2. MvcPager帮助文档 - MvcAjaxOptions 类
  3. [译]NectarJS:编译JavaScript为任意平台原生二进制代码
  4. 阿里云云服务器的端口配置问题
  5. C++ 复制构造函数
  6. 【转】15个最受欢迎的Python开源框架
  7. Windows 搭建 C/C++ 开发环境之Eclipse
  8. iOS开发点击UIButton实现UIView的旋转
  9. 获取GitHub上远程分支内容
  10. 第二十二章:动画(八)