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

经过多天的摸索,参考多个系统以及自己的经验,《沐雪微店系统 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. Fragment为什么须要无参构造方法

    日前在项目代码里遇到偷懒使用重写Fragment带参构造方法来传参的做法,顿生好奇,继承android.support.v4.app.Fragment而又不写无参构造方法不是会出现lint错误编译不通 ...

  2. thread-01

    // 8:15 AM/09/28/2017 #pragma once #include <iostream> // std::cout #include <thread> // ...

  3. .Net Core中简单使用MongoDB

    MongoDB 是由C++语言编写的,是一个基于分布式且面向文档存储的开源数据库系统. 下载地址: https://www.mongodb.com/download-center/community ...

  4. 十分钟搭建自己的私有NuGet服务器-BaGet

    目录 前言 开始 搭建BaGet 上传程序包 在vs中使用 其他 最后 前言 NuGet是用于微软.NET(包括 .NET Core)开发平台的软件包管理器.NuGet能够令你在项目中添加.移除和更新 ...

  5. IDEA使用GsonFormat

    安装GsonFormat插件 因为下载了最新版的idea2020.1.3发现GsonFormat在Idea商店不见了,所以去jetbrains官网下载jar包来安装插件https://plugins. ...

  6. 8月份Python招聘情况怎么样?Python爬取招聘数据,并进行分析

    前言 拉勾招聘是专业的互联网求职招聘平台.致力于提供真实可靠的互联网招聘求职找工作信息.今天我们一起使用 python 采集拉钩的 python 招聘信息,分析一下找到高薪工作需要掌握哪些技术 开发环 ...

  7. 东哥学Node的故事——内存管理

    前言 东哥是一个平凡的前端攻城狮,北邮网研院研二在读,刚接触Node不久,心里充满了对Node的好奇和崇拜,只听噗通一声,掉入了Node的坑... 于是东哥开始疯狂地看Node相关的书籍,这不,就学到 ...

  8. IIS站点管理-IIS站点以管理员身份或指定用户运行

    PS:概要.背景.结语都是日常“装X”,可以跳过直接看应用程序池设置 环境:Windows Server 2008.阿里云ECS.IIS7.0 概要 IIS应用程序默认情况下,是使用内置帐户运行的,权 ...

  9. 比原链(Bytom)正式开源Bytom-JavaScript库

    12月13日,比原链(Bytom)正式开源Bytom-JavaScript库,这个库是官方原生支持的新一代JavaScript SDK接口.JavaScript是世界上最多人使用的解释性脚本语言,JS ...

  10. db2 创建function报错

     create function fun_fw_sfyczy(pi_operunitid varchar(2)) returns varchar(2)LANGUAGE SQL BEGIN ATOMIC ...