ABP-Book Store Application中文讲解 - Part 5: Authorization

ABP-Book Store Application中文讲解 - Part 5: Authorization

  1. 汇总

ABP-Book Store Application中文讲解-汇总-CSDN博客

  1. 前一章

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 and permissionGuard 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博客

相关推荐
ou.cs8 分钟前
c# :this() 和 :base()区别
开发语言·c#
汪小白JIY3 小时前
【C#】异步和多线程
c#·thread·async·task·threapool
AI.NET 极客圈4 小时前
.NET 原生驾驭 AI 新基建实战系列(六):Pinecone ── 托管向量数据库的向量数据库的云原生先锋
数据库·人工智能·.net
宝桥南山5 小时前
DeepSeek - 尝试一下GitHub Models中的DeepSeek
microsoft·ai·微软·c#·github·.net
追逐时光者5 小时前
C#/.NET/.NET Core优秀项目和框架2025年5月简报
后端·.net
crary,记忆9 小时前
Angular报错:cann‘t bind to ngClass since it is‘t a known property of div
前端·javascript·angular·angular.js
lljss202011 小时前
C# 一个解决方案放一个dll项目,一个dll测试项目 ,调试dll项目的源码
c#
ghost14320 小时前
C#学习第27天:时间和日期的处理
开发语言·学习·c#
jason成都20 小时前
c#压缩与解压缩-SharpCompress
开发语言·c#
傻啦嘿哟21 小时前
从零开始:用Tkinter打造你的第一个Python桌面应用
开发语言·c#