ABP入门系列目录——学习Abp框架之实操演练

源码路径:Github-LearningMpaAbp


完成了简单的增删改查和分页功能,是不是觉得少了点什么?
是的,少了权限管理。既然涉及到了权限,那我们就细化下任务清单的功能点:

  • 登录的用户才能查看任务清单
  • 用户可以无限创建任务并分配给自己,但只能对自己创建的任务进行查找、修改
  • 管理员可以创建任务并分配给他人
  • 管理员具有删除任务的权限

从以上的信息中,我们可以提取出以下权限:

  1. 任务分配权限
  2. 任务删除权限

那我们下面就来实现针对这两个权限的管理:

一、ABP权限管理的实现

1、先来看看权限定义相关类型:

从该类型依赖图中我们可以看出:

  • Permission:权限类,定义了权限的属性。
  • PermissionDictionary:继承自Dictionary<string, Permission>类,存储permission对象的字典。
  • IPermisssionDefinitionContext:定义了CreatePermissionGetPermissionOrNull方法,分别用来创建和获取权限。
  • AuthorizationProvider:抽象类,在Module中实现该接口来定义权限。
  • PermissionManager:权限管理类,继承自PermissionDefinitionContextBase主要提供了获取权限的系列方法。

2、再来看看权限检查相关类型

从该类型依赖图中简要梳理下核心类:

  • IPermissionChecker:从接口命名就明白,这个是用来进行权限检查的。我们可以自己实现它,也可以使用module-zero中给出的实现。
  • NullPermissionChecker:当未实现IPermissionChecker,系统会默认使用此类将权限赋予给每个用户。
  • AbpAuthorizeAttribute:权限检查特性,在应用服务层标注需要的权限。
  • AbpAllowAnonymousAttribute:匿名访问特性,忽略权限检查,用于应用服务层。在mvc和webapi中使用[AllowAnonymous]
  • AuthorizationInterceptor:授权拦截器,用来拦截定义了AbpAuthorizeAttribute特性的方法。

核心的几个类就讲到这里,具体的实现,可以自行查看源码一探究竟。

二、定义权限

从上节中我们知道在不同的Module中通过继承AuthorizationProvider来定义权限。ABP模板项目中已经在领域层,也就是.Core结尾的项目中,定义了xxxxxxAuthorizationProvider类继承自AuthorizationProvider

1、权限包含哪些属性

  • Name:系统中 唯一的名字。最好为权限的名字定义一个const字符串而不是变量字符串。我们偏向使用“.”符号用于有层次的名字,但这不是强制的。你可以设置任何你喜欢的名字,唯一的一点是保证它必须是唯一的。
  • DisplayName:用于以后在UI上显示权限的本地化字符串。
  • Description:用于以后在UI上显示权限定义的本地化字符串。
  • IsGrantedByDefault:表示该权限是否授予给所有登录的用户,除非该权限显式禁止未授予给用户。该值一般默认为false。
  • MultiTenancySides:对于多租户应用,租户或者租主可以使用同一个权限。这是一个Flags枚举,因此一个权限可以用于租户和租主。
  • featureDependency:可以用于声明一个功能的依赖。因此,只有功能依赖满足了,该权限才会被授予。

2、定义任务分配和任务删除权限

ABP模板项目默认已经在.Core/Authorization/目录下创建了AuthorizationProvider的派生类xxxxAuthorizationProvider.cs
其中代码为:

public override void SetPermissions(IPermissionDefinitionContext context)
{
//Common permissions
var pages = context.GetPermissionOrNull(PermissionNames.Pages);
if (pages == null)
pages = context.CreatePermission(PermissionNames.Pages, L("Pages")); var users = pages.CreateChildPermission(PermissionNames.Pages_Users, L("Users")); //Host permissions
var tenants = pages.CreateChildPermission(PermissionNames.Pages_Tenants, L("Tenants"),
multiTenancySides: MultiTenancySides.Host);
}

可以看出主要添加了三个权限,Pages、Users、Tenants。
依葫芦画瓢,咱们创建一个TaskAuthorizationProvider继承自AuthorizationProvider
代码如下:

public class TaskAuthorizationProvider : AuthorizationProvider
{
public override void SetPermissions(IPermissionDefinitionContext context)
{
//Common permissions
var pages = context.GetPermissionOrNull(PermissionNames.Pages);
if (pages == null)
pages = context.CreatePermission(PermissionNames.Pages, L("Pages")); //Tasks
var tasks = pages.CreateChildPermission(PermissionNames.Pages_Tasks, L("Tasks"));
tasks.CreateChildPermission(PermissionNames.Pages_Tasks_AssignPerson, L("AssignTaskToPerson"));
tasks.CreateChildPermission(PermissionNames.Pages_Tasks_Delete, L("DeleteTask"));
} private static ILocalizableString L(string name)
{
return new LocalizableString(name, LearningMpaAbpConsts.LocalizationSourceName);
}
}

并在常量PermissionNames类中维护唯一用户名。

public const string Pages_Tasks = "Pages.Pages.Tasks";

public const string Pages_Tasks_AssignPerson = "Pages.Pages.Tasks.AssignPerson";

public const string Pages_Tasks_Delete = "Pages.Pages.Tasks.Delete";

需要本地化显示的,则需要分别维护本地化xml文件,这里忽略此步。

3、注册TaskAuthorizationProvider

定位到.Core/xxxCoreModule.cs文件中发现Abp已经为默认实现的的xxxxAuthorizationProvider.cs注册了。
Configuration.Authorization.Providers.Add<LearningMpaAbpAuthorizationProvider>();
因为ABP是模块化的,当你需要为自己自定义的模块定义权限时,
不要忘记在自己定义的Module中注册自己实现的AuthorizationProvider(授权提供器)。
所以,还是依葫芦画瓢,注册TaskAuthorizationProvider
Configuration.Authorization.Providers.Add<TaskAuthorizationProvider>();

三、权限检查

1、使用[AbpAuthorize]特性

在应用服务层中直接使用[AbpAuthorize]特性,但在MVC控制器中使用[AbpMvcAuthorize]特性,Web API控制器中使用[AbpApiAuthorize]

我们在应用服务层给删除操作定义权限检查:

[AbpAuthorize(PermissionNames.Pages_Tasks_Delete)]
public void DeleteTask(int taskId)
{
var task = _taskRepository.Get(taskId);
if (task != null)
_taskRepository.Delete(task);
}

F5运行,去删除某一任务,将获得以下提示:

2、使用IPermissionChecker

删除任务是一个独立的操作,所以我们可以直接使用上面特性声明的方式来进行权限检查。
但是针对【任务分配】这个操作,它其实是任务创建、编辑中的一个子操作。所以我们不能直接使用特性声明的方式来进行权限检查。这一次我们使用IPermissionChecker来进行检查。

2.1、应用服务层注入了PermissionChecker属性
因为授权一般在应用服务层中进行,所以ABP默认在ApplicationService基类注入并定义了PermissionChecker属性。这样,在应用服务层就可以直接使用PermissionChecker属性进行权限检查。
2.2、修改创建任务方法,加入权限检查:

public int CreateTask(CreateTaskInput input)
{
//We can use Logger, it's defined in ApplicationService class.
Logger.Info("Creating a task for input: " + input); //获取当前用户
var currentUser = AsyncHelper.RunSync(this.GetCurrentUserAsync); //判断用户是否有权限
if (input.AssignedPersonId.HasValue && input.AssignedPersonId.Value != currentUser.Id)
PermissionChecker.Authorize(PermissionNames.Pages_Tasks_AssignPerson); var task = Mapper.Map<Task>(input); int result = _taskRepository.InsertAndGetId(task); //只有创建成功才发送邮件和通知
if (result > 0)
{
task.CreationTime = Clock.Now; if (input.AssignedPersonId.HasValue)
{
task.AssignedPerson = _userRepository.Load(input.AssignedPersonId.Value);
var message = "You hava been assigned one task into your todo list."; //TODO:需要重新配置QQ邮箱密码
//SmtpEmailSender emailSender = new SmtpEmailSender(_smtpEmialSenderConfig);
//emailSender.Send("ysjshengjie@qq.com", task.AssignedPerson.EmailAddress, "New Todo item", message); _notificationPublisher.Publish("NewTask", new MessageNotificationData(message), null,
NotificationSeverity.Info, new[] { task.AssignedPerson.ToUserIdentifier() });
}
}

其中权限检查代码为:PermissionChecker.Authorize(PermissionNames.Pages_Tasks_AssignPerson);这种方式当没有权限时,将直接抛出异常。当启用<customErrors mode="On" />时,将跳转至Error视图并显示以下信息。

2.3、修改编辑任务方法,加入权限检查:

public void UpdateTask(UpdateTaskInput input)
{
//We can use Logger, it's defined in ApplicationService base class.
Logger.Info("Updating a task for input: " + input); //获取当前用户
var currentUser = AsyncHelper.RunSync(this.GetCurrentUserAsync);
//获取是否有权限
bool canAssignTaskToOther = PermissionChecker.IsGranted(PermissionNames.Pages_Tasks_AssignPerson);
//如果任务已经分配且未分配给自己,且不具有分配任务权限,则抛出异常
if (input.AssignedPersonId.HasValue && input.AssignedPersonId.Value != currentUser.Id && !canAssignTaskToOther)
{
throw new AbpAuthorizationException("没有分配任务给他人的权限!");
} var updateTask = Mapper.Map<Task>(input);
_taskRepository.Update(updateTask);
}

其中权限检查代码为PermissionChecker.IsGranted(PermissionNames.Pages_Tasks_AssignPerson);IsGranted()方法返回true or false。

2.4、Razor页面如何进行权限检查
视图基类定义了IsGranted方法来检查当前用户是否具有权限。我们可以在_List.cshtml.cs中加入以下代码来控制是否显示删除按钮。

@if (IsGranted(PermissionNames.Pages_Tasks_Delete))
{
<button type="button" class="btn btn-success" onclick="deleteTask(@task.Id);">Delete</button>
}

2.5、js代码如何进行权限检查
abp.auth命名空间下定义了权限相关的API,在js中我们可以直接使用。
这里不再举例。

四、将新增的权限赋予给Admin

完成了权限的定义和检查,我们如何进行权限设置呢,如何为角色或用户赋予权限呢?
在ABP模板项目中暂未提供用户角色权限管理功能,但在AbpZero中提供了该功能,支持按用户或角色赋予权限。那咋办呢?
咱们退而求其次,在数据库初始化的时候,将权限赋给Admin。
但是我们的数据库已经建立好了啊?
反正是测试库,删掉重建呗。

1、删除数据库

怎么删数据库,自己应该知道吧。

2、代码中为Admin赋予权限

打开基础设施层,即以EntityFramework结尾的项目中,定位到Migrations\SeedData文件夹,分别在
HostRoleAndUserCreatorTenantRoleAndUserBuilder两个类中添加以下代码:

var taskPermissions = PermissionFinder.GetAllPermissions(new PersonAppAuthorizationProvider()).ToList();
permissions.AddRange(taskPermissions);

3、重新编译整个项目,执行Update-Database

查看数据库,发现已经将Permission赋予给了admin


总结:

本节主要讲解了ABP权限管理的基本实现方式,以及如何定义、使用和添加权限。

在ABP模板项目中暂未提供用户角色权限管理功能,但在AbpZero中提供了该功能,支持按用户或角色赋予权限。这一节先暂时不表,等我研究通彻了再和大家娓娓道来。

 

ABP —— 权限管理的更多相关文章

  1. ABP module-zero +AdminLTE+Bootstrap Table+jQuery权限管理系统第十三节--RBAC模式及ABP权限管理(附送福利)

    ABP+AdminLTE+Bootstrap Table权限管理系统一期 Github:https://github.com/Jimmey-Jiang/ABP-ASP.NET-Boilerplate- ...

  2. ABP入门系列(9)——权限管理

    ABP入门系列目录--学习Abp框架之实操演练 源码路径:Github-LearningMpaAbp 完成了简单的增删改查和分页功能,是不是觉得少了点什么? 是的,少了权限管理.既然涉及到了权限,那我 ...

  3. Module Zero之权限管理

    返回<Module Zero学习目录> 概览介绍 角色权限 用户权限 概览介绍 Module-Zero实现了ABP授权系统的IPermissionChecker接口.这篇文章中,我们将会看 ...

  4. ASP.NET 开发必备知识点(2):那些年追过的ASP.NET权限管理

    一.前言 在前一篇文章已经为大家介绍了OWIN和Katana,有了对他们的了解之后,才能更好地去学习Asp.net Identity,因为Asp.net Identity的实现集成了Owin.其实在A ...

  5. ABP 权限拦截 第二篇

    由于访问人数过多,我今天从新整理一下ABP权限认证机制,帮助大家更容易读懂 1.Abp 的权限拦截主要通过过滤器,    public class AbpAuthorizationFilter : I ...

  6. 权限管理UI

    vue+vuex+vue-router+EF的权限管理系统 演示网站 首先说下这个项目吧.如标题一样是基于VUE+.NET开发的框架,也是群友一直吼吼吼要一个vue版本的ABP框架.我们先来看看首页吧 ...

  7. 第一章 权限管理DEMO简介

    源代码GitHub:https://github.com/ZhaoRd/Zrd_0001_AuthorityManagement 1.系列介绍 工作已有五年之久,一直有想通过博客写点自己知道的,在博客 ...

  8. Android权限管理之RxPermission解决Android 6.0 适配问题

    前言: 上篇重点学习了Android 6.0的运行时权限,今天还是围绕着Android 6.0权限适配来总结学习,这里主要介绍一下我们公司解决Android 6.0权限适配的方案:RxJava+RxP ...

  9. Android权限管理之Android 6.0运行时权限及解决办法

    前言: 今天还是围绕着最近面试的一个热门话题Android 6.0权限适配来总结学习,其实Android 6.0权限适配我们公司是在今年5月份才开始做,算是比较晚的吧,不过现在Android 6.0以 ...

  10. Android权限管理之Permission权限机制及使用

    前言: 最近突然喜欢上一句诗:"宠辱不惊,看庭前花开花落:去留无意,望天空云卷云舒." 哈哈~,这个和今天的主题无关,最近只要不学习总觉得生活中少了点什么,所以想着围绕着最近面试过 ...

随机推荐

  1. 仿MFC的消息印射(全局函数的实现)

    //弄了个仿MFC消息映射,这是全局函数都好弄,照着MFC就弄出来了,//在vs2017上可以通过#include <windows.h> #include "resource. ...

  2. CentOS 7.3离线安装 JDK,Mariadb

    1.环境准备 #链接:https://pan.baidu.com/s/1rcLrELaLHBJI0pKQQFOnNA #提取码:f1a2 2.安装 # 离线文件位置 /home/bw/# 将目标机器系 ...

  3. Win11减少C盘占用及清爽系统配置教程

    Win11减少C盘占用及清爽系统配置教程 你是否有过C盘爆满而不得不重装系统的经历?你是否有过因为C盘爆满而不得不不断的拓展空间的无奈?你是否有过已经将软件安装在D盘但C盘的空间还是在日益变满的痛苦? ...

  4. 【Python + Appium】之元素定位总结(更新)

    一.ID定位 uiautomatorviewer里面的:resource-id driver.find_element(By.ID,"com.csks.businesses:id/tv_nu ...

  5. ASP.NET Core – Upload and Download Files (上传和下载文件)

    前言 以前得文章 Asp.net core 学习笔记 ( upload/download files 文件上传与下载 ), 这篇是修订版. Handle Upload File (处理上传文件) 我的 ...

  6. DOM – IntersectionObserver

    介绍 IntersectionObserver 的作用是监听某个元素是否出现在框内 (比如 viewport). 它可以实现 lazy load image, 一开始图片是没有加载的, 当图片出现在 ...

  7. Angular 学习笔记 work with zip (压缩文件格式)

    最近在做批量创建. 上回说到了 读写 excel, 那么就可以通过 excel 的资料来创建资料了.但是资料经常会有图片,而 excel 里面放图片有点不太好. 于是就想 upload excel 的 ...

  8. Identity – Without Identity Framework

    前言 上一回研究 Authenticate 和 Authorization 已经是 2 年前了. 业务需求一直没有增长, 所以也没有再去提升它了. 但最近业务开始上去了. 荒废的功夫又得拾起来了. 上 ...

  9. 第16天:信息打点-CDN绕过&业务部署&漏洞回链&接口探针&全网扫描&反向邮件

    #CDN配置: 配置1:加速域名-需要启用加速的域名 配置2:加速区域-需要启用加速的地区 配置3:加速类型-需要启用加速的资源 #参考知识: 超级Ping:http://www.17ce.com/ ...

  10. .Net 6 SignalR 实际业务开发中遇到的问题及解决办法

    一.SiganlR 使用的协议类型 1.websocket即时通讯协议 2.Server-Sent Events(SSE)服务器事件 3.longpolling 长轮询. 如果客户端开启协商,会按顺序 ...