前面几篇已经说到模块的增删改查功能的实现,接下来咋们看看怎么实现系统的权限配置和实现
一、自定义权限名称
在项目TestApp.BookStore.Application.Contracts的Permissions文件下的BookStorePermissions类中,脚本如下:
namespace TestApp.BookStore.Permissions;
public static class BookStorePermissions
{
public const string GroupName = " BookStore " ;
// Add your own permission names. Example:
// public const string MyPermission1 = GroupName + ".MyPermission1";
public static class Books
{
public const string Default = GroupName + " .Books " ;
public const string Create = Default + " .Create " ;
public const string Edit = Default + " .Edit " ;
public const string Delete = Default + " .Delete " ;
}
}
二、权限定义
在项目TestApp.BookStore.Application.Contracts的Permissions文件下的BookStorePermissionDefinitionProvider类中,脚本如下:
using TestApp.BookStore.Localization;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Localization;
namespace TestApp.BookStore.Permissions;
public class BookStorePermissionDefinitionProvider : PermissionDefinitionProvider
{
public override void Define(IPermissionDefinitionContext context)
{
var myGroup = context.AddGroup(BookStorePermissions.GroupName,L(" Permission:BookStore " ));
// Define your own permissions here. Example:
// myGroup.AddPermission(BookStorePermissions.MyPermission1, L("Permission:MyPermission1"));
var booksPermission = myGroup.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);
}
}
定义BookStorePermissions.Books.Default、Create、Edit、Delete时千万注意别写重复了,系统一运行就会报Permissions.Books重复定义错误
这个类定义了一个 权限组 (在UI上分组权限, 下文会看到) 和 权限组中的4个权限 . 而且, 创建 , 编辑 和 删除 是 BookStorePermissions.Books.Default
权限的子权限. 仅当父权限被选择 时, 子权限才能被选择
里面有用到本地化文本,所以又得配置一下本地化文本(TestApp.BookStore.Domain.Shared
项目的 Localization/BookStore
文件夹中的 en.json
),新增脚本如下:
" 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 "
此时就可以在权限页面(管理>身份认证管理>角色>操作>权限)看到所配置的权限目录,如下:
此时就可以在系统配置自己的所需的权限,但是会发现一个问题,配置好了不会生效,那是因为我们只是实现的权限配置,还没有完整在增删改查的操作点使用对应的权限配置,具体操作如下
三、应用层和HTTP API设置权限策略
TestApp.BookStore.Application项目Books文件夹,打开 the BookAppService
类, 设置策略名称为上面定义的权限名称。脚本如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using TestApp.BookStore.Permissions;
namespace TestApp.BookStore.Books
{
public class BookAppService :
CrudAppService <
Book, // The Book entity
BookDto, // Used to show books
Guid, // Primary key of the book entity
PagedAndSortedResultRequestDto, // Used for paging/sorting
CreateUpdateBookDto>, // Used to create/update a book
IBookAppService
{
public BookAppService(IRepository<Book, Guid> repositoty)
: base (repositoty)
{
GetPolicyName = BookStorePermissions.Books.Default;
GetListPolicyName = BookStorePermissions.Books.Default;
CreatePolicyName = BookStorePermissions.Books.Create;
UpdatePolicyName = BookStorePermissions.Books.Edit;
DeletePolicyName = BookStorePermissions.Books.Delete;
}
}
}
加入代码到构造器. 基类中的 CrudAppService
自动在CRUD操作中使用这些权限. 这不仅实现了 应用服务 的安全性, 也实现了 HTTP API 安全性, 因为如前解释的, HTTP API 自动使用这些服务
四、Razor页面授权
TestApp.BookStore.Web项目打开 BookStoreWebModule
在 ConfigureServices
方法中加入以下代码:
Configure<RazorPagesOptions>(options =>
{
options.Conventions.AuthorizePage( " /Books/Index " , BookStorePermissions.Books.Default);
options.Conventions.AuthorizePage( " /Books/CreateModal " , BookStorePermissions.Books.Create);
options.Conventions.AuthorizePage( " /Books/EditModal " , BookStorePermissions.Books.Edit);
});
五、菜单(List)/新建(Create)/编辑(Edit)/删除(Delete)操作点使用权限配置
菜单(List)
TestApp.BookStore.Web项目Menus文件夹BookStoreMenuContributor类,将原来的BookStore菜单脚本:
context.Menu.AddItem(
new ApplicationMenuItem(
" BooksStore " ,
l[ " Menu:BookStore " ],
icon: " fa fa-book "
).AddItem(
new ApplicationMenuItem(
" BooksStore.Books " ,
l[ " Menu:Books " ],
url: " /Books "
)
)
);
修改为(就是加上权限配置判断):
var bookStoreMenu = new ApplicationMenuItem(
" BooksStore " ,
l[ " Menu:BookStore " ],
icon: " fa fa-book "
);
context.Menu.AddItem(bookStoreMenu);
// CHECK the PERMISSION
if (await context.IsGrantedAsync(BookStorePermissions.Books.Default))
{
bookStoreMenu.AddItem( new ApplicationMenuItem(
" BooksStore.Books " ,
l[ " Menu:Books " ],
url: " /Books "
));
}
新建(Create)
打开 Pages/Books/Index.cshtml
文件将之前的New book按钮脚本,修改为:
@if (await AuthorizationService.IsGrantedAsync(BookStorePermissions.Books.Create))
{
<abp-button id=" NewBookButton "
text =" @L[ " NewBook" ].Value "
icon =" plus "
button -type=" Primary " />
}
最终Index.cshtml脚本如下:
@page
@using TestApp.BookStore.Localization
@using TestApp.BookStore.Web.Pages.Books
@using TestApp.BookStore.Permissions
@using Microsoft.Extensions.Localization
@using Microsoft.AspNetCore.Authorization
@model TestApp.BookStore.Web.Pages.Books.IndexModel
@inject IStringLocalizer <BookStoreResource> L
@inject IAuthorizationService AuthorizationService
@section scripts
{
<abp-script src=" /Pages/Books/Index.js " />
}
<abp-card>
<abp-card-header>
<abp-row>
<abp-column size-md=" _6 " >
<abp-card-title>@L[" Books " ]</abp-card-title>
</abp-column>
<abp-column size-md=" _6 " class =" text-right " >
@if ( await AuthorizationService.IsGrantedAsync(BookStorePermissions.Books.Create))
{
<abp-button id=" NewBookButton "
text =" @L[ " NewBook" ].Value "
icon =" plus "
button -type=" Primary " />
}
</abp-column>
</abp-row>
</abp-card-header>
<abp-card-body>
<abp-table striped-rows=" true " id=" BooksTable " ></abp-table>
</abp-card-body>
</abp-card>
加入 @inject IAuthorizationService AuthorizationService
以访问授权服务.
使用 @if (await AuthorizationService.IsGrantedAsync(BookStorePermissions.Books.Create))
检查图书创建权限, 条件显示 新建图书 按钮.
编辑(Edit)
打开 Pages/Books/Index.js
文件将之前的Edit按钮脚本,修改为:
{
text: l( ' Edit ' ),
visible: abp.auth.isGranted( ' BookStore.Books.Edit ' ), // CHECK for the PERMISSION
action: function (data) {
editModal.open({ id: data.record.id });
}
},
删除(Delete)
打开 Pages/Books/Index.js
文件将之前的Delete按钮脚本,修改为:
{
text: l( ' Delete ' ),
visible: abp.auth.isGranted( ' BookStore.Books.Delete ' ), // CHECK for the PERMISSION
confirmMessage: function (data) {
return l(
' BookDeletionConfirmationMessage ' ,
data.record.name
);
},
action: function (data) {
testApp.bookStore.books.book
.delete(data.record.id)
.then(function () {
abp.notify.info(
l( ' SuccessfullyDeleted ' )
);
dataTable.ajax.reload();
});
}
}
最终js脚本如下:
$(function () {
var l = abp.localization.getResource(' BookStore ' );
// 获取列表
var dataTable = $(' #BooksTable ' ).DataTable(
abp.libs.datatables.normalizeConfiguration({
serverSide: true ,
paging: true ,
order: [[ 1 , " asc " ]],
searching: false ,
scrollX: true ,
ajax: abp.libs.datatables.createAjax(testApp.bookStore.books.book.getList),
columnDefs: [
{
title: l( ' Actions ' ),
rowAction: {
items:
[
{
text: l( ' Edit ' ),
visible: abp.auth.isGranted( ' BookStore.Books.Edit ' ), // CHECK for the PERMISSION
action: function (data) {
editModal.open({ id: data.record.id });
}
},
{
text: l( ' Delete ' ),
visible: abp.auth.isGranted( ' BookStore.Books.Delete ' ), // CHECK for the PERMISSION
confirmMessage: function (data) {
return l(
' BookDeletionConfirmationMessage ' ,
data.record.name
);
},
action: function (data) {
testApp.bookStore.books.book
.delete(data.record.id)
.then(function () {
abp.notify.info(
l( ' SuccessfullyDeleted ' )
);
dataTable.ajax.reload();
});
}
}
]
}
},
{
title: l( ' Name ' ),
data: " name "
},
{
title: l( ' Type ' ),
data: " type " ,
render: function (data) {
return l(' Enum:BookType: ' + data);
}
},
{
title: l( ' PublishDate ' ),
data: " publishDate " ,
render: function (data) {
return luxon
.DateTime
.fromISO(data, {
locale: abp.localization.currentCulture.name
}).toLocaleString();
}
},
{
title: l( ' Price ' ),
data: " price "
},
{
title: l( ' CreationTime ' ), data: " creationTime " ,
render: function (data) {
return luxon
.DateTime
.fromISO(data, {
locale: abp.localization.currentCulture.name
}).toLocaleString(luxon.DateTime.DATETIME_SHORT);
}
}
]
})
);
// 新增操作
var createModal = new abp.ModalManager(abp.appPath + ' Books/CreateModal ' );
createModal.onResult(function () {
dataTable.ajax.reload();
});
$( ' #NewBookButton ' ).click(function (e) {
e.preventDefault();
createModal.open();
});
// 修改操作(columnDefs新增Actions操作列)
var editModal = new abp.ModalManager(abp.appPath + ' Books/EditModal ' );
editModal.onResult(function () {
dataTable.ajax.reload();
});
})
在此配置权限,测试勾选Creating new books,则Book列表就有New book按钮,其他操作也是如此。本文测试截图admin无删除操作,附截图如下:
以上就是本项目模板权限配置的内容,在此记录为了加深印象同时方便后者参考学习!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架