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

经过多天的摸索,参考多个系统以及自己的经验,《沐雪微店系统 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. Java进阶专题(十一) 想理解JVM看了这篇文章,就知道了!(中)

    前言 ​ 上次讲解了JVM内存相关知识,今天继续JVM专题. JVM垃圾回收算法 什么是垃圾回收 ​ 程序的运行必然需要申请内存资源,无效的对象资源如果不及时处理就会一直占有内存资源,最终将导致内存溢 ...

  2. 实现了__iter__和__next__的对象是迭代器

    class MyList(object): """自定义的一个可迭代对象""" def __init__(self): self.items ...

  3. luogu P4775 [NOI2018]情报中心 线段树合并 虚树 树的直径trick

    LINK:情报中心 神题! 写了一下午 写到肚子疼. 调了一晚上 调到ex 用的是网上dalao的方法 跑的挺快的. 对于链的暴力 我不太会kk. 直接说正解吧: 分类讨论两种情况: 1 答案的两条链 ...

  4. 经验分享:一个 30 岁的人是如何转行做程序员,进入IT行业的?

    大约一年以前,我成为了一名全职开发者,我想要总结一下这一年的经验,并且和所有人分享,一个 30 多岁的人是如何进入科技行业的: 改变职业是一件吓人的事情,有时候还会成为一件危险的事情.年龄越大,危险就 ...

  5. luogu4443 coci 2017 Dajave

    题目 给出一个长度为2^M的排列,元素分别是0, 1, 2, ... , 2^M -1. 选择其中某个非空连续子序列,然后允许交换这个排列中某两个不同的数,然后使得这个连续子序列的所有数的按位异或(b ...

  6. python3 openssl问题(贼有用)

    目录 一.问题描述 二.排查过程 三.总结 四.写在最后 一.问题描述 在python3 执行任何的request请求时,都会报以下的错误,纵观全网,以下基本尝试过了,对于我这个是无效的,后来不知道怎 ...

  7. tracebace用法

    介绍一下traceback 平时看到的程序的错误信息也就是traceback信息 举个简单例子: import traceback try: s = [1, 2, 3] print s[5] exce ...

  8. 【FZYZOJ】「Paladin」瀑布 题解(期望+递推)

    题目描述 CX在Minecraft里建造了一个刷怪塔来杀僵尸.刷怪塔的是一个极高极高的空中浮塔,边缘是瀑布.如果僵尸被冲入瀑布中,就会掉下浮塔摔死.浮塔每天只能工作 $t$秒,刷怪笼只能生成 $N$  ...

  9. Jenkins(Extended E-mail Notification)邮箱配置正确但是并没有发送邮件

    废话 近期在把之前的接口自动化demo与jenkins集成,昨天发现了邮件配置正确但是没有发送邮件的问题,通过勾选系统设置 - >Extended E-mail Notification -&g ...

  10. 2020-04-10:有一个 API 服务,后端只使用了数据库来持久化数据,平时在 API 网关上监控到响应时间平均值大约为10ms,现在突然上涨到 5s,而且一直居高不下。请简单描述一下你排查这个问题的思路。

    福哥答案2020-04-11: 1 排查api服务 是否是有大量请求 2 查看mysql的系统情况 cpu 磁盘io 连接数 还是要先定位问题出现在哪个环节