ABP-Book Store Application中文讲解 - Part 5: Authorization
- 汇总
ABP-Book Store Application中文讲解-汇总-CSDN博客
- 前一章
ABP-Book Store Application中文讲解 - Part 4: Integration Tests-CSDN博客
项目之间的引用关系。
ABP有一套完整的权限控制系统,可以通知页面的显示级别或者按钮级别。具体可以参考官网的例子:Authorization | ABP.IO Documentation
如果我们没有特殊的权限要求,可以完全借用ABP的权限管理,ABP帮我们设计好了一套UI和后端API的流程,我们只需要遵守其规则即可。本文主要是用于介绍基于ABP的permission规则如何控制Book页面的权限。
目录
[1. 命名规则](#1. 命名规则)
[2. 添加权限到BookStorePermissions.cs](#2. 添加权限到BookStorePermissions.cs)
[3. 添加本地化资源](#3. 添加本地化资源)
[4. 定义权限到BookStorePermissionDefinitionProvider](#4. 定义权限到BookStorePermissionDefinitionProvider)
[5. API应用权限](#5. API应用权限)
[5.1 默认设置](#5.1 默认设置)
[5.2 利用Authorize设置](#5.2 利用Authorize设置)
[6. 在UI端应用权限-Angular Guard Configuration](#6. 在UI端应用权限-Angular Guard Configuration)
[6.1 添加AuthGuard和PermissionGuard控制页面权限](#6.1 添加AuthGuard和PermissionGuard控制页面权限)
[6.2 html页面添加abpPermission,控制按钮权限](#6.2 html页面添加abpPermission,控制按钮权限)
[6.3 html页面添加abpPermission绑定多个权限值](#6.3 html页面添加abpPermission绑定多个权限值)
[7. Permission UI](#7. Permission UI)
[8. 后端API报错](#8. 后端API报错)
[8.1 设置多个启动项](#8.1 设置多个启动项)
[8.2 The Libs folder is missing](#8.2 The Libs folder is missing)
[9. 继续学习](#9. 继续学习)
1. 命名规则
我们需要在BookStorePermission.cs中定义权限名称,此名称会用于本地化资源的key和UI端的key。
虽然ABP没有强制要求命名规则,但是它任然推荐用模块名的命名规则去定义权限。
2. 添加权限到BookStorePermissions.cs
在Acme.BookStore.Application.Contracts中展开Permissions文件夹,可以找到BookStorePermissions.cs,然后打开后编辑。
cs
namespace Acme.BookStore.Permissions;
public static class BookStorePermissions
{
public const string GroupName = "BookStore";
// other permissions...
// 定义Books权限
public static class Books
{
public const string Default = GroupName + ".Books";// 控制Book页面权限
public const string Create = Default + ".Create";// 控制Create button的隐藏显示
public const string Edit = Default + ".Edit";// 控制Edit button的隐藏显示
public const string Delete = Default + ".Delete";// Delete button的隐藏显示
}
}
3. 添加本地化资源
在Acme.BookStore.Domain.Shared中打开Localization\BookStore,在en.json和zh-Hans.json添加权限名称。
en.json
cs
"Permission:BookStore": "Book Store",
"Permission:Books": "Book Management",
"Permission:Books.Create": "Creating new books",
"Permission:Books.Edit": "Editing the books",
"Permission:Books.Delete": "Deleting the books"
zh-Hans.json
cs
"Permission:BookStore": "书店",
"Permission:Books": "书籍管理",
"Permission:Books.Create": "新建书籍",
"Permission:Books.Edit": "编辑书籍",
"Permission:Books.Delete": "删除书籍"
完整json-en.json
cs
{
"Culture": "en",
"Texts": {
"Menu:Home": "Home",
"Welcome": "Welcome",
"LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP. For more information, visit abp.io.",
// 以下内容是新增内容
"Menu:BookStore": "Book Store",
"Menu:Books": "Books",
"Actions": "Actions",
"Close": "Close",
"Delete": "Delete",
"Edit": "Edit",
"Save": "Save",
"Cancel": "Cancel",
"Update": "Update",
"PublishDate": "Publish date",
"NewBook": "New book",
"EditBook": "Edit book",
"Name": "Name",
"Type": "Type",
"Price": "Price",
"CreationTime": "Creation time",
"AreYouSure": "Are you sure?",
"AreYouSureToDelete": "Are you sure you want to delete this item?",
"Enum:BookType.0": "Undefined",
"Enum:BookType.1": "Adventure",
"Enum:BookType.2": "Biography",
"Enum:BookType.3": "Dystopia",
"Enum:BookType.4": "Fantastic",
"Enum:BookType.5": "Horror",
"Enum:BookType.6": "Science",
"Enum:BookType.7": "Science fiction",
"Enum:BookType.8": "Poetry",
"Permission:BookStore": "Book Store",
"Permission:Books": "Book Management",
"Permission:Books.Create": "Creating new books",
"Permission:Books.Edit": "Editing the books",
"Permission:Books.Delete": "Deleting the books"
}
}
完整zh-Hans.json
cs
{
"culture": "zh-Hans",
"texts": {
"AppName": "BookStore",
"Menu:Home": "首页",
"Welcome": "欢迎",
"LongWelcomeMessage": "欢迎使用本应用程序。这是一个基于 ABP 框架的启动项目。更多信息,请访问 abp.io。",
// 以下内容是新增内容
"Menu:BookStore": "书店",
"Menu:Books": "书籍管理",
"Actions": "操作",
"Close": "关闭",
"Delete": "删除",
"Edit": "编辑",
"Save": "保存",
"Cancel": "取消",
"Update": "更新",
"PublishDate": "发布日期",
"NewBook": "新增书",
"EditBook": "编辑书",
"Name": "名字",
"Type": "类型",
"Price": "价格",
"CreationTime": "新建日期",
"AreYouSure": "你确定吗?",
"AreYouSureToDelete": "你确定你要删除此条目吗?",
"Enum:BookType.0": "未定义",
"Enum:BookType.1": "冒险",
"Enum:BookType.2": "传记",
"Enum:BookType.3": "反乌托邦",
"Enum:BookType.4": "奇幻",
"Enum:BookType.5": "恐怖",
"Enum:BookType.6": "科学",
"Enum:BookType.7": "科幻",
"Enum:BookType.8": "诗歌",
"Permission:BookStore": "书店",
"Permission:Books": "书籍管理",
"Permission:Books.Create": "新建书籍",
"Permission:Books.Edit": "编辑书籍",
"Permission:Books.Delete": "删除书籍"
}
}
4. 定义权限到BookStorePermissionDefinitionProvider
在Acme.BookStore.Application.Contracts中展开Permissions文件夹,可以找到BookStorePermissionDefinitionProvider.cs,然后打开后编辑。
cs
using Acme.BookStore.Localization;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Localization;
namespace Acme.BookStore.Permissions;
public class BookStorePermissionDefinitionProvider : PermissionDefinitionProvider
{
public override void Define(IPermissionDefinitionContext context)
{
var bookStoreGroup = context.AddGroup(BookStorePermissions.GroupName, L("Permission:BookStore"));
var booksPermission = bookStoreGroup.AddPermission(BookStorePermissions.Books.Default, L("Permission:Books"));
booksPermission.AddChild(BookStorePermissions.Books.Create, L("Permission:Books.Create"));
booksPermission.AddChild(BookStorePermissions.Books.Edit, L("Permission:Books.Edit"));
booksPermission.AddChild(BookStorePermissions.Books.Delete, L("Permission:Books.Delete"));
}
private static LocalizableString L(string name)
{
return LocalizableString.Create<BookStoreResource>(name);
}
}
5. API应用权限
5.1 默认设置
打开BookAppService.cs类,并将策略名称设置为上面定义的权限名称:
cs
using Acme.BookStore.Permissions;
using System;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
namespace Acme.BookStore.Books
{
public class BookAppService :
CrudAppService<
Book, //The Book entity
BookDto, //Used to show books in UI
Guid, //Primary key of the book entity
PagedAndSortedResultRequestDto, //Used for paging/sorting
CreateUpdateBookDto>, //Used to create/update a book
IBookAppService //implement the IBookAppService
{
public BookAppService(IRepository<Book, Guid> repository) : base(repository)
{
GetPolicyName = BookStorePermissions.Books.Default;// Default
GetListPolicyName = BookStorePermissions.Books.Default;
CreatePolicyName = BookStorePermissions.Books.Create;
UpdatePolicyName = BookStorePermissions.Books.Edit;
DeletePolicyName = BookStorePermissions.Books.Delete;
}
}
}
5.2 利用Authorize设置
此处也可以通过设置[Authorize(...)]去控制权限,例如:
cs
[Authorize(BookStorePermissions.Books.Create)]
public override Task<BookDto> CreateAsync(CreateUpdateBookDto input)
{
return base.CreateAsync(input);
}
因为此处用的是CrudAppService,所以只能通过override实现权限的重新设置。
如果直接继承的ApplicationService,则不需要override。
例子如下:
var authorManagement = myGroup.AddPermission("Author_Management"); authorManagement.AddChild("Author_Management_Create_Books"); authorManagement.AddChild("Author_Management_Edit_Books"); authorManagement.AddChild("Author_Management_Delete_Books");
cs
[Authorize("Author_Management")]
public class AuthorAppService : ApplicationService, IAuthorAppService
{
public Task<List<AuthorDto>> GetListAsync()
{
...
}
public Task<AuthorDto> GetAsync(Guid id)
{
...
}
[Authorize("Author_Management_Create_Books")]
public Task CreateAsync(CreateAuthorDto input)
{
...
}
[Authorize("Author_Management_Edit_Books")]
public Task UpdateAsync(CreateAuthorDto input)
{
...
}
[Authorize("Author_Management_Delete_Books")]
public Task DeleteAsync(CreateAuthorDto input)
{
...
}
}
6. 在UI端应用权限-Angular Guard Configuration
6.1 添加AuthGuard和PermissionGuard控制页面权限
打开/src/app/book/book-routing.module.ts
- Imported
authGuard
andpermissionGuard
from the@abp/ng.core
.- Added
canActivate: [authGuard, permissionGuard]
to the route definition.
TypeScript
import { authGuard, permissionGuard } from '@abp/ng.core';
const routes: Routes = [
{ path: '', component: BookComponent, canActivate: [authGuard, permissionGuard] },
];
打开/src/app/route.provider.ts,在**/book-store** 和**/books**添加 requiredPolicy: 'BookStore.Books'
TypeScript
import { RoutesService, eLayoutType } from '@abp/ng.core';
import { APP_INITIALIZER } from '@angular/core';
export const APP_ROUTE_PROVIDER = [
{ provide: APP_INITIALIZER, useFactory: configureRoutes, deps: [RoutesService], multi: true },
];
function configureRoutes(routesService: RoutesService) {
return () => {
routesService.add([
{
path: '/',
name: '::Menu:Home',
iconClass: 'fas fa-home',
order: 1,
layout: eLayoutType.application,
},
{
path: '/book-store',
name: '::Menu:BookStore',
iconClass: 'fas fa-book',
order: 2,
layout: eLayoutType.application,
requiredPolicy: 'BookStore.Books',// new added
},
{
path: '/books',
name: '::Menu:Books',
// iconClass: 'fas fa-user',
parentName: '::Menu:BookStore',
order: 3,
layout: eLayoutType.application,
requiredPolicy: 'BookStore.Books',// new added
}
]);
};
}
6.2 html页面添加abpPermission,控制按钮权限
打开/src/app/book/book.component.html
新建按钮权限

html
<!-- Add the abpPermission directive -->
<button *abpPermission="'BookStore.Books.Create'" id="create" class="btn btn-primary" type="button" (click)="createBook()">
<i class="fa fa-plus me-1"></i>
<span>{{ '::NewBook' | abpLocalization }}</span>
</button>
*abpPermission="'BookStore.Books.Create'"
如果当前用户没有BookStore.Books.Create权限,则新建按钮会被隐藏。
编辑和删除按钮权限

html
<!-- Add the abpPermission directive -->
<button *abpPermission="'BookStore.Books.Edit'" ngbDropdownItem (click)="editBook(row.id)">
{{ '::Edit' | abpLocalization }}
</button>
<!-- Add the abpPermission directive -->
<button *abpPermission="'BookStore.Books.Delete'" ngbDropdownItem (click)="delete(row.id)">
{{ '::Delete' | abpLocalization }}
</button>
*abpPermission="'BookStore.Books.Edit'"
如果当前用户没有BookStore.Books.Edit权限,则编辑按钮会被隐藏。
*abpPermission="'BookStore.Books.Delete'"
如果当前用户没有BookStore.Books.Delete权限,则删除按钮会被隐藏。
6.3 html页面添加abpPermission绑定多个权限值
如果用户没有编辑和删除权限,可以通过以下代码隐藏操作列。
*abpPermission="'BookStore.Books.Edit' or 'BookStore.Books.Delete'"
html
<ngx-datatable-column *abpPermission="'BookStore.Books.Edit' or 'BookStore.Books.Delete'" [name]="'::Actions' | abpLocalization" [maxWidth]="150" [sortable]="false">
<ng-template let-row="row" ngx-datatable-cell-template>
<div ngbDropdown container="body" class="d-inline-block">
<button class="btn btn-primary btn-sm dropdown-toggle" data-toggle="dropdown"
aria-haspopup="true" ngbDropdownToggle>
<i class="fa fa-cog me-1"></i>{{ '::Actions' | abpLocalization }}
</button>
<div ngbDropdownMenu>
<button *abpPermission="'BookStore.Books.Edit'" ngbDropdownItem (click)="editBook(row.id)">
{{ '::Edit' | abpLocalization }}
</button>
<!-- add the Delete button -->
<button *abpPermission="'BookStore.Books.Delete'" ngbDropdownItem (click)="delete(row.id)">
{{ '::Delete' | abpLocalization }}
</button>
</div>
</div>
</ng-template>
</ngx-datatable-column>

7. Permission UI
当我们完成以上步骤后,重新编译程序,打开浏览器输入localhost:4200,用admin账号登录成功后既可以看到Administration菜单,然后一次打开 Administration -> Identity -> Roles page.
可以checked或者unchecked权限后,刷新页面,然后到Books页面去检测权限。

8. 后端API报错
8.1 设置多个启动项
权限验证是的登录需要用到Acme.BookStore.AuthServer
API需要启动Acme.BookStore.HttpApi.Host。
可以通过以下方式设置多个启动项:右击Solution--》Properties。选择Multiple startup projects。

8.2 The Libs folder is missing
设置成功后,点击F5启动,如果启动报错The Libs folder is missing.

可以根据提示在根目录打开CMD.exe 然后运行以下命令:
abp install-libs
如果运行出错或者运行半天没反应,可以通过npm intsall 单独安装。
需要安装node_modules目录如下:(有package.json的项目都需要运行npm install)
Acme.BookStore\aspnet-core\src\Acme.BookStore.AuthServer
Acme.BookStore\aspnet-core\src\Acme.BookStore.Blazor.WebApp
Acme.BookStore\aspnet-core\src\Acme.BookStore.Blazor.WebApp.Tiered

9. 继续学习
ABP-Book Store Application中文讲解 - Part 6: Authors: Domain Layer-CSDN博客