ABP入门系列目录——学习Abp框架之实操演练
源码路径:Github-LearningMpaAbphtml
完成了简单的增删改查和分页功能,是否是以为少了点什么?
是的,少了权限管理。既然涉及到了权限,那咱们就细化下任务清单的功能点:git
从以上的信息中,咱们能够提取出如下权限:github
那咱们下面就来实现针对这两个权限的管理:web
从该类型依赖图中咱们能够看出:数据库
CreatePermission
和GetPermissionOrNull
方法,分别用来建立和获取权限。PermissionDefinitionContextBase
主要提供了获取权限的系列方法。从该类型依赖图中简要梳理下核心类:api
IPermissionChecker
,系统会默认使用此类将权限赋予给每一个用户。[AllowAnonymous]
。AbpAuthorizeAttribute
特性的方法。核心的几个类就讲到这里,具体的实现,能够自行查看源码一探究竟。mvc
从上节中咱们知道在不一样的Module中经过继承AuthorizationProvider
来定义权限。ABP模板项目中已经在领域层,也就是.Core结尾的项目中,定义了xxxxxxAuthorizationProvider类继承自AuthorizationProvider
。app
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
。
代码以下:ide
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文件,这里忽略此步。
定位到.Core/xxxCoreModule.cs文件中发现Abp已经为默认实现的的xxxxAuthorizationProvider.cs
注册了。
Configuration.Authorization.Providers.Add<LearningMpaAbpAuthorizationProvider>();
由于ABP是模块化的,当你须要为本身自定义的模块定义权限时,
不要忘记在本身定义的Module中注册本身实现的AuthorizationProvider(受权提供器)。
因此,仍是依葫芦画瓢,注册TaskAuthorizationProvider
Configuration.Authorization.Providers.Add<TaskAuthorizationProvider>();
在应用服务层中直接使用[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运行,去删除某一任务,将得到如下提示:
删除任务是一个独立的操做,因此咱们能够直接使用上面特性声明的方式来进行权限检查。
可是针对【任务分配】这个操做,它实际上是任务建立、编辑中的一个子操做。因此咱们不能直接使用特性声明的方式来进行权限检查。这一次咱们使用IPermissionChecker
来进行检查。
2.一、应用服务层注入了PermissionChecker属性
由于受权通常在应用服务层中进行,因此ABP默认在ApplicationService基类注入并定义了PermissionChecker属性。这样,在应用服务层就能够直接使用PermissionChecker属性进行权限检查。
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.三、修改编辑任务方法,加入权限检查:
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.四、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.五、js代码如何进行权限检查
abp.auth
命名空间下定义了权限相关的API,在js中咱们能够直接使用。
这里再也不举例。
完成了权限的定义和检查,咱们如何进行权限设置呢,如何为角色或用户赋予权限呢?
在ABP模板项目中暂未提供用户角色权限管理功能,但在AbpZero中提供了该功能,支持按用户或角色赋予权限。那咋办呢?
我们退而求其次,在数据库初始化的时候,将权限赋给Admin。
可是咱们的数据库已经创建好了啊?
反正是测试库,删掉重建呗。
怎么删数据库,本身应该知道吧。
打开基础设施层,即以EntityFramework结尾的项目中,定位到Migrations\SeedData
文件夹,分别在
HostRoleAndUserCreator
和TenantRoleAndUserBuilder
两个类中添加如下代码:
var taskPermissions = PermissionFinder.GetAllPermissions(new PersonAppAuthorizationProvider()).ToList(); permissions.AddRange(taskPermissions);
查看数据库,发现已经将Permission赋予给了admin
本节主要讲解了ABP权限管理的基本实现方式,以及如何定义、使用和添加权限。
在ABP模板项目中暂未提供用户角色权限管理功能,但在AbpZero中提供了该功能,支持按用户或角色赋予权限。这一节先暂时不表,等我研究通彻了再和你们娓娓道来。
遗留问题: