我们在做项目项目,经常会碰到权限体系,权限体系属于系统架构的一个最底层的功能,也是非常重要的功能,几乎在每个项目都会用到。那么我们该如何设计一个比较合理的且扩展性较强的权限体系呢?

经过多天的摸索,参考多个系统以及自己的经验,《沐雪微店系统 NetCore3.1》的权限体系是这样的。

  • 一、首先确定几个重要实体的关系:用户,角色,权限;这三者之间的关系如下:

其中:

1、用户与角色是1对多关系(  1个用户只有1个角色,1个角色可以对应多个用户);

2、角色与权限组是1对1关系( 1个角色只有1个权限组,1个权限组只有1个角色)。

3、一个权限组里包含1个菜单和多个操作按钮;

4、操作按钮预先定义好最多的情况的枚举值;(比如  查看,新增,修改,删除,审核,下载,确认,回复)

这样的架构,相对来说比较合理,适合绝大多数系统使用了。(设计的越灵活,控制起来越困难,越困难越容易出现错误,所以要根据实际的情况控制灵活到什么程度即可;不要一口吃成胖子,想要一次性搞出无限灵活的权限系统。)

  • 二、对几个实体进行CRUD单实体操作(增,删,改,查)

1、菜单的增删改查;

2、权限组的增删改查:

3、用户的增删改查:

  • 三、用代码来实现权限系统

大家在菜单管理页面,应该注意到有3个字段:--编码,链接地址和权限值;这些是我们写代码的时候需要用的。

1、创建一个控制器的父类--BaseController,这里只要有一个可以获取当前登录者的方法即可,类似如下代码:

        /// <summary>
/// 当前登录者
/// </summary>
public PTLoginResp CurrentUser
{
get
{
PTLoginResp currentUser = new PTLoginResp();
if (User.Identity.IsAuthenticated)
{
var claimIdentity = (ClaimsIdentity)User.Identity;
string key = claimIdentity.FindFirst("tokenid").Value;
currentUser.id = LoginCredentials.PFDecodeRedisKeyOfUserId(key); currentUser.user_name = claimIdentity.FindFirst("user_name").Value;
currentUser.real_name = claimIdentity.FindFirst("real_name").Value;
currentUser.mobile_phone = claimIdentity.FindFirst("mobile_phone").Value;
currentUser.role_id = ConvertHelper.LongParse(claimIdentity.FindFirst("role_id").Value, ); }
return currentUser;
}
}

2、创建具体的业务控制器和相应的Action,并且集成BaseController;

3、创建一个Action的权限属性特性方法,比如下面代码:

    /// <summary>
/// Action的权限属性
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class ActionAuthDescriptorAttribute : System.Attribute
{ public ActionAuthDescriptorAttribute(string NavCode, AuthTypeEnum AuthType)
{
this.NavCode = NavCode;
this.AuthType = AuthType; }
/// <summary>
/// 权限组code
/// </summary>
public string NavCode { get; set; } /// <summary>
/// 权限操作的枚举值,比如Show
/// </summary>
public AuthTypeEnum AuthType { get; set; } }

这样,我们就可以在Action上加上这个特性了:

        /// <summary>
/// 《沐雪微店系统 Netcore 3.1》添加管理员页面
/// </summary>
/// <returns></returns>
[ActionAuthDescriptor("manager_mgr", AuthTypeEnum.Add)]
public async Task< ActionResult> Create()
{
ManagerInfo managerAdd = new ManagerInfo();
managerAdd.using_type = UsingTypeEnum.sys.ToString();
managerAdd.is_lock = false; List<muxue_role> roleList =await _roleService.GetRoleList(UsingTypeEnum.sys);
roleList = roleList.FindAll(p => p.is_sys == false);
ViewBag.roleList = roleList; return View(managerAdd);
}

4、开始写权限验证过滤器了PrivilegeFilter:

验证的大概逻辑如下:

 /// <summary>
/// 《沐雪微店系统 Netcore 3.1》权限验证逻辑
/// (集成BaseController的控制器,需要登录后才可以)
/// 1、看下Controller是否有AllRightsAttribute;
/// 2、看下Action是否有AllRightsAttribute,是否有ActionAuthDescriptorAttribute
/// 3、(1)若Action有AllRightsAttribute,则说明任何登录者都可以访问;
/// (2)若Action没有AllRightsAttribute,但是Controller上有,则说明任何登录者都可以访问;
/// (3)若Action和Controller都没有,并且Aciton也没有ActionAuthDescriptorAttribute, 则任何人都不可以访问;
/// 4、看下Action是否有ActionAuthDescriptorAttribute,则任何人都不可以访问;
/// 5、若有ActionAuthDescriptorAttribute,则进行判断该Action是否有该角色的权限;
/// </summary>
/// <param name="context"></param>

重点的代码如下:

 public override void OnActionExecuting(ActionExecutingContext context)
{ var controller = context.Controller as BaseController;
if (controller == null)
{
base.OnActionExecuting(context);
return;
} if (controller.CurrentUser == null)
{
//《沐雪微店系统 Netcore 3.1》去登录
// context.HttpContext.ChallengeAsync().Wait();
base.OnActionExecuting(context);
return;
} string requestMethod = context.HttpContext.Request.Method.ToLower(); ControllerActionDescriptor ad = context.ActionDescriptor as ControllerActionDescriptor;
bool isControllerAllRights = ad.ControllerTypeInfo.IsDefined(typeof(AllRightsAttribute), false);
bool isActionAllRights = ad.MethodInfo.IsDefined(typeof(AllRightsAttribute), false);
bool isActionAuthDescriptor = ad.MethodInfo.IsDefined(typeof(ActionAuthDescriptorAttribute), false);
if (!isControllerAllRights && !isActionAllRights && !isActionAuthDescriptor)
{
//没有权限访问
if (requestMethod == "get")
{
context.Result = new RedirectResult("/Error/Index?msg=没有权限");
base.OnActionExecuting(context);
return;
}
else
{
context.Result = new JsonResult(NoPrivPostJsonResult());
base.OnActionExecuting(context);
return;
}
}
if (isActionAllRights)
{
base.OnActionExecuting(context);
return;
}
if (isControllerAllRights && !isActionAllRights && !isActionAuthDescriptor)
{
base.OnActionExecuting(context);
return;
} if (isActionAuthDescriptor)
{
var authorizeAttr = ad.MethodInfo.GetCustomAttributes(typeof(ActionAuthDescriptorAttribute), false).FirstOrDefault() as ActionAuthDescriptorAttribute;
string navCode = authorizeAttr.NavCode;
AuthTypeEnum authType = authorizeAttr.AuthType; long current_role_id = controller.CurrentUser.role_id;
bool hasRolePriv = _roleprivilegeService.HasRolePriv(current_role_id, navCode, authType).Result;
if (!hasRolePriv)
{//没有权限
if (requestMethod == "get")
{
context.Result = new RedirectResult("/Error/Index?msg=没有权限");
base.OnActionExecuting(context);
return;
}
else
{
context.Result = new JsonResult(NoPrivPostJsonResult());
base.OnActionExecuting(context);
return;
}
}
} base.OnActionExecuting(context); }

将这个Filter添加到StartUp里:

            services.AddMvc(options =>
{
if (!env.IsDevelopment())
{
}
options.Filters.Add<LogstashFilter>();
options.Filters.Add<PrivilegeFilter>();//权限验证
options.Filters.Add<XcActionFilter>();
options.Filters.Add<GlobalExceptions>();
})

这样就完成了权限控制了。

asp.net Core3.1自定义权限体系-菜单和操作按钮权限的更多相关文章

  1. [转]PostgreSQL 逻辑结构 和 权限体系 介绍

    摘要: 本文旨在帮助用户理解PostgreSQL的逻辑结构和权限体系,帮助用户快速的理解和管理数据库的权限. 逻辑结构 最上层是实例,实例中允许创建多个数据库,每个数据库中可以创建多个schema,每 ...

  2. Asp.net Identity身份与权限体系设计

    1 Identity 介绍 2 授权系统 图1 体系结构 3 自定义 Attribute 自定义 Attribute 继承于 AuthorizeAttribute,AuthorizeAttribute ...

  3. .net core3.1 abp动态菜单和动态权限(思路) (二)

    ps:本文需要先把abp的源码下载一份来下,跟着一起找实现,更容易懂 在abp中,对于权限和菜单使用静态来管理,菜单的加载是在登陆页面的地方(具体是怎么知道的,浏览器按F12,然后去sources中去 ...

  4. 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(20)-权限管理系统-根据权限获取菜单

    原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(20)-权限管理系统-根据权限获取菜单 不知不觉到20讲,真是漫长的日子,可惜最近工作挺忙,要不可以有更多 ...

  5. vue的自定义指令控制菜单权限

    用户登录后,选择子节点,节点中含有多个菜单,可以根据后台返回的权限数据进行权限控制 在vue上挂载自定义指令方法,根据后台返回权限移除相应节点 import Cookies from "js ...

  6. 浅谈Oracle权限体系

    对于数据库来讲,安全性的重要程度不言而喻,今天我们就来聊一聊Oracle的权限体系. 1.账户管理 在此之前,先解释下一个容易混淆的概念:模式.所谓模式,指的是用户账户所拥有的一组对象(比如表,索引, ...

  7. sqlserver权限体系(上)

    简介 权限两个字,一个权力,一个限制.在软件领域通俗的解释就是哪些人可以对哪些资源做哪些操作. 在SQL Server中,”哪些人”,“哪些资源”,”哪些操作”则分别对应SQL Server中的三个对 ...

  8. 理解SQL Server中的权限体系(上)----主体

    原文:http://www.cnblogs.com/CareySon/archive/2012/04/10/mssql-security-principal.html 简介 权限两个字,一个权力,一个 ...

  9. [2017-08-21]Abp系列——如何使用Abp插件机制(注册权限、菜单、路由)

    本系列目录:Abp介绍和经验分享-目录 Abp的模块系统支持插件机制,可以在指定目录中放置模块程序集,然后应用程序启动时会搜索该目录,加载其中所有程序集中的模块. 如何使用这套机制进行功能插件化开发? ...

随机推荐

  1. Python List index()方法

    描述 index() 函数用于从列表中找出某个值第一个匹配项的索引位置.高佣联盟 www.cgewang.com 语法 index()方法语法: list.index(x[, start[, end] ...

  2. PHP strftime() 函数

    ------------恢复内容开始------------ 实例 根据区域设置格式化本地日期和时间: <?php echo(strftime("%B %d %Y, %X %Z&quo ...

  3. PHP xml_set_element_handler() 函数

    定义和用法 xml_set_element_handler() 函数规定在 XML 文档中元素的起始和终止调用的函数. 如果成功,该函数则返回 TRUE.如果失败,则返回 FALSE.高佣联盟 www ...

  4. 7.12 NOI模拟赛 积性函数求和 数论基础变换 莫比乌斯反演

    神题! 一眼powerful number 复习了一下+推半天. 可以发现G函数只能为\(\sum_{d}[d|x]d\) 不断的推 可以发现最后需要求很多块G函数的前缀和 发现只有\(\sqrt(n ...

  5. 安装ElasticSearch遇到的深坑

    实验需要ES,安装过程中遇到一些奇葩的问题,记录下.下面介绍下安装步骤: 第一步:安装java ES是运行在java虚拟机上面的,所以首先需要安装java环境,安装过程不再赘述,唯一需要注意的是ES对 ...

  6. 正确的使用HttpClient

    快捷的网络请求,多用HttpClient 但是常规的写法会一大片的TIME_OUT 比如这样的例子 static async Task<string> TestHttpClient(str ...

  7. 7月15日考试 题解(链表+状压DP+思维题)

    前言:蒟蒻太弱了,全打的暴力QAQ. --------------------- T1 小Z的求和 题目大意:求$\sum\limits_{i=1}^n \sum\limits_{j=i}^n kth ...

  8. python4.1定义函数

    def add(a,b,c,d): e=a+b+c-d return e result=add(21,32,43,56)print("加和结果是:",result) def zzj ...

  9. Linux安装配置PHPmyadmin

    进官网下载zip安装包 wget https://files.phpmyadmin.net/phpMyAdmin/5.0.1/phpMyAdmin-5.0.1-all-languages.zip 安装 ...

  10. Linux(Centos 7)下安装Git并配置连接GitHub

    1.安装git  Centos7 查看git --version 2.配置用户名密码 git config --global user.name "xxx" git config ...