Util应用框架快速入门(5) – 权限入门

本文将引导你运行Util权限管理模块,并对UI按钮和API操作进行访问控制.

Util平台介绍

Util应用框架是一组类库,它们提供了有用的功能.

虽然Util配套代码生成器能够帮助你创建项目基架,但直接使用它们的成本依然高昂.

第一个挡在前面的障碍是权限功能,它是任何业务项目的基石.

为了减轻使用Util应用框架的负担,我们创建了该项目, 名为 Util Platform, 即 Util平台.

Util平台处于起步阶段,目前提供了基于资源和角色的权限模块,可以控制前端菜单和按钮,并能同时控制API的访问.

后续将持续更新,添加更多基础功能.

开源协议: MIT

可以在商业项目随意使用.

欢迎参与贡献

你如果感兴趣,可以参与该项目的开发, 共同创建基础业务功能,为 .NET 生态添砖加瓦.

  • Util应用框架交流QQ群(24791014)

Util平台项目介绍

为了满足单体架构微服务架构的需求, Util平台分为三套项目.

  • Util.Platform.Single

    Util.Platform.Single 是Util平台单体架构版本.

  • Util.Platform.Dapr

    Util.Platform.Dapr 是Util平台微服务架构版本.

  • Util.Platform.Share

    Util.Platform.Share 是Util平台的共享库,抽取单体架构版本和微服务架构版本的共享代码,并发布到Nuget供两个版本使用.

Util平台功能列表

  • 系统功能

    • 登录
    • 退出登录
  • 权限管理模块

    • 应用程序管理
    • 声明管理
    • 资源管理
      • 模块资源管理
      • 操作资源管理
      • 身份资源管理
      • Api资源管理
    • 用户管理
    • 角色管理
      • 将用户添加到角色
      • 从角色移除用户
    • 权限管理
      • 授予角色操作权限
      • 拒绝角色操作权限
      • 授予角色API权限
      • 拒绝角色API权限

准备

拉取 Util.Platform.Single 项目代码.

git clone https://gitee.com/util-core/Util.Platform.Single.git 

如果已拉取,请更新到最新代码.

运行项目

打开 Util.Platform.Single.sln 解决方案.

数据迁移

设置 Util.Platform.Api 为启动项目.

Util应用框架快速入门(5) - 权限入门

打开 appsettings.Development.json 开发配置文件.

Util应用框架快速入门(5) - 权限入门

DatabaseType 配置项用于指定当前使用的数据库类型,可选值为:

  • SqlServer
  • PgSql
  • MySql

Util.Platform.Single 目前支持以上三种数据库,如果需要支持其它数据库,请告知.

检查你使用的数据库连接字符串是否正确.

F5 键,启动 Util.Platform.Api 项目.

启动时,会自动运行 EntityFrameworkCore 迁移命令,创建迁移文件目录.

Util应用框架快速入门(5) - 权限入门

会同时创建三种数据库项目迁移文件目录.

如果没有配置MySql连接字符串,或 MySql 连接失败, 则无法创建MySql迁移文件目录,并会产生一个异常,不用理会它.

查看数据库,可以看到数据库已创建.

Util应用框架快速入门(5) - 权限入门

使用 Swagger 测试 Web Api 访问控制

启动完成, 弹出 Swagger 页面.

Util应用框架快速入门(5) - 权限入门

下面选择一个最简单的操作进行测试,执行 Application 的 /api/Application/enabled 操作.

Util应用框架快速入门(5) - 权限入门

返回消息 code 为 2.

Code 是 Util 应用框架约定的返回结果代码, 2 代表未授权 .

Util应用框架快速入门(5) - 权限入门

Util.Platform.Api 项目默认开启了API访问控制,需要先进行登录认证.

Util.Platform.Api 项目的 Swagger 已经配置好 OAuth 认证.

点击 Swagger Authorize 按钮.

Util应用框架快速入门(5) - 权限入门

弹出 Available authorizations 对话框,点击 Authorize 按钮.

Util应用框架快速入门(5) - 权限入门

进入登录页面,如下所示.

Util应用框架快速入门(5) - 权限入门

数据迁移默认创建两个用户: admin 和 test .

admin用户是管理员,test是普通用户.

输入用户 test , 密码 test ,使用普通用户登录.

登录成功,跳回 Swagger 页面,点击 Close 按钮关闭对话框.

Util应用框架快速入门(5) - 权限入门

重新执行 Application 的 /api/Application/enabled 操作.

Util应用框架快速入门(5) - 权限入门

可以看到,成功返回数据,说明已经授权成功.

那么是不是只要登录,就能操作所有API接口?

下面执行 Application 的 POST /api/Application 操作,它表示创建应用程序.

Util应用框架快速入门(5) - 权限入门

返回结果代码为 2,表明未授权,无法访问 API,因为没有给 test 用户设置创建应用程序的权限.

运行管理后台UI

进入 Util.Platform.SinglesrcUtil.Platform.Ui.IdentityClientApp 目录.

执行命令,还原 npm 并启动 Angular 开发服务器.

.start.ps1 

设置 Util.Platform.Ui.IdentityUtil.Platform.Api 为启动项目.

Util应用框架快速入门(5) - 权限入门

F5 键启动项目.

弹出 Api Swagger 和 Angular UI 页面.

Angular UI 已经开启了授权路由守卫,未授权则跳转到登录页面.

使用 admin 用户名登录,密码 admin.

登录成功,进入管理后台UI,如下所示.

Util应用框架快速入门(5) - 权限入门

查看权限管理模块

查看应用程序

应用程序用于支持多个业务子系统的访问控制.

点击左侧 应用程序 菜单项,如下所示.

Util应用框架快速入门(5) - 权限入门

数据迁移默认创建的应用程序,名为 管理系统.

你可以添加新的应用程序,点击 创建 按钮,打开 创建应用程序 对话框.

应用程序还用于管理 Identity Server 身份服务器客户端信息.

Util应用框架快速入门(5) - 权限入门

查看声明

声明是登录认证后可以在用户会话中访问的信息项.

Util应用框架快速入门(5) - 权限入门

声明非常简单,使用表格列表进行编辑.

查看资源

资源是任何需要访问控制的东西.

它是权限管理模块的核心.

点击左侧 资源 菜单项,如下所示.

Util应用框架快速入门(5) - 权限入门

查看模块资源

模块资源 用于按功能模块进行分层设置, 同时也显示为前端的 菜单.

UI 左侧菜单即是由模块资源配置的.

并不是所有的模块资源都会在菜单上显示,比如资源菜单下的内部导航菜单,也可以在模块资源中配置,但不会在菜单上显示.

Util应用框架快速入门(5) - 权限入门

点击 创建 按钮,弹出 创建模块 对话框.

父模块是一个下拉树组件,如下所示.

Util应用框架快速入门(5) - 权限入门

我们顺便看看 Util UI对下拉树绑定这类常见需求提供的支持.

首先查看 html 代码.

打开 Util.Platform.Ui.Identity/Pages/Routes/Identity/Module/Edit.cshtml 文件,如下所示.

Util应用框架快速入门(5) - 权限入门

Razor TagHelper 标签设置url直接发起web api请求.

这并非 Angular 推荐用法, 而是从之前 EasyUI 保留下来的经验,对于常规项目,这样能大幅提升开发效率.

对于更复杂的场景,你可以使用 Angular 标准玩法,创建独立的服务,使用服务加载数据,并绑定到组件上.

<util-tree-select for="ParentId" query-param="queryParam" load-mode="Sync" url="module/tree" default-expand-all="true"     sort="SortId" label-text="identity.module.parentId" control-span="8"> </util-tree-select> 

下面来查看 Angular 组件 typescript 脚本代码.

打开 Util.Platform.Ui.Identity/ClientApp/src/app/routes/identity/module/module-edit.component.ts 文件,如下所示.

Util应用框架快速入门(5) - 权限入门

可以看到,代码非常简单,没有加载父模块下拉树组件的代码.

/**  * 模块编辑页  */ @Component({     selector: 'module-edit',     templateUrl: environment.production ? './html/edit.component.html' : '/view/routes/identity/module/edit' }) export class ModuleEditComponent extends TreeEditComponentBase<ModuleViewModel> {     /**      * 查询参数      */     queryParam: ResourceQuery;     /**      * 应用程序标识      */     @Input() applicationId;     /**      * 应用程序名称      */     @Input() applicationName;      /**      * 初始化模块编辑页      * @param injector 注入器      */     constructor(injector: Injector) {         super(injector);         let param = this.util.dialog.getData<any>();         if (param) {             this.applicationId = param.applicationId;             this.applicationName = param.applicationName;         }     }      /**      * 初始化      */     ngOnInit() {         super.ngOnInit();         this.model.applicationId = this.applicationId;         this.queryParam = this.createQuery();     }      /**      * 创建模型      */     createModel() {         let result = new ModuleViewModel();         result.enabled = true;         return result;     }      /**      * 创建查询参数      */     protected createQuery() {         let result = new ResourceQuery();         result.applicationId = this.applicationId;         return result;     }      /**      * 获取基地址      */     protected getBaseUrl() {         return "module";     }      /**      * 选择图标      */     selectIcon(icon) {         this.model.icon = icon;     } } 

最后,查看 Web Api 控制器的代码.

打开 Util.Platform.Api/Controllers/Identity/ModuleController.cs 文件,如下所示.

Util应用框架快速入门(5) - 权限入门

模块控制器从 NgZorroTreeControllerBase 基类继承,已经封装将树形数据转换成 Ng Zorro 树形组件需要的数据格式.

NgZorroTreeControllerBase 基类提供的 QueryAsync 方法用于为树形表格提供数据,TreeQueryAsync 方法为树形或下拉树形提供数据.

查看操作资源

点击 模块资源 列表 资源设置 按钮,打开 操作资源 列表, 如下所示.

Util应用框架快速入门(5) - 权限入门

操作资源 列表是一个内嵌表格,为模块资源提供细粒度访问控制,比如控制页面上的按钮.

资源还有两种常见类型, 资源和 行集 资源.

资源用来控制显示的字段.

行集 资源用来控制不同角色显示不同的内容,俗称数据权限.

行集资源需要使用规约对象封装查询条件,并接入 Util 授权体系.

这两种资源尚未实现,待基础功能完善以后提供,如果你的项目对数据权限控制有需求,可以告知,我们将提前实现它.

点击 操作资源 创建 按钮,打开 创建操作权限 对话框.

Util应用框架快速入门(5) - 权限入门

操作名称输入框提示常用操作,可以从中选择,或手工输入.

资源最重要的属性是标识.

对于UI按钮的控制,可以使用有意义的标识, 比如 application.create, 表示创建应用程序.

资源的定义由开发人员根据控制粒度决定,除了在管理系统添加资源数据,还需要修改相应代码.

设置操作权限

下面以 创建应用程序 操作为例,介绍控制 UI 按钮和 API 需要的步骤.

  • 添加 创建应用程序 操作资源.

    数据迁移已经创建了该资源,标识为 application.create.

Util应用框架快速入门(5) - 权限入门

  • UI 按钮访问控制

    打开 Util.Platform.Ui.Identity/Pages/Routes/Identity/Application/Index.cshtml 文件,如下所示.

Util应用框架快速入门(5) - 权限入门

只需要把 application.create 操作资源标识设置到 acl 属性即可.

acl 属性是 Ng Alain 提供的访问控制指令 *aclIf, 已经将 acl 属性全局添加到 Util UI所有 TagHelper 标签.

  • Api 访问控制

    打开 Util.Platform.Api/Controllers/Identity/ApplicationController.cs 文件,代码简化如下.

    /// <summary> /// 应用程序控制器 /// </summary> [Acl( "application.view" )] public class ApplicationController : CrudControllerBase<ApplicationDto, ApplicationQuery> {   /// <summary>   /// 初始化应用程序控制器   /// </summary>   /// <param name="service">应用程序服务</param>   public ApplicationController( IApplicationService service ) : base( service ) {       ApplicationService = service;   }    /// <summary>   /// 应用程序服务   /// </summary>   protected IApplicationService ApplicationService { get; }    /// <summary>   /// 创建   /// </summary>   /// <param name="request">创建参数</param>   [HttpPost]   [Acl( "application.create" )]   public new async Task<IActionResult> CreateAsync( ApplicationDto request ) {       return await base.CreateAsync( request );   } } 

    注意 ApplicationController 控制器上面的 [Acl( "application.view" )] 特性.

    Asp.Net Core 自带了一个授权特性 [Authorize] ,它默认的行为是只要登录认证成功,就能进行任何操作.

    Authorize 特性可以设置 Roles 属性, 设置硬编码的角色列表,这不太灵活.

    Authorize 特性还能设置 Policy 自定义授权策略, 这是一种灵活的授权方式,但每个需要授权的API都要设置 Policy 很费力.

    Util Acl 特性从 Authorize 继承,并封装了特定的授权策略.

    与 Authorize 的 Roles 不同的是, Acl 并不设置角色,因为角色是动态的,可能随时增加减少,所以设置角色是一种不太靠谱的方法,只适合角色固定的项目.

    Acl 特性设置的是资源标识, 资源标识是固定不变的,理解这一点是将权限从业务逻辑中剥离出来的关键.

    application.view 是查看应用程序操作资源.

    任何功能页面都需要查看权限,如果没有细粒度控制需求,对整个页面和API进行控制即可.

    现在只要某个角色拥有 application.view 操作资源,他就能对控制器中所有方法进行访问.

    当需要进行更加细粒度的控制时,只需要在某个控制器方法上添加 [Acl] 特性,并设置相应的资源标识即可.

    CreateAsync 方法添加了 [Acl( "application.create" )] 特性,这说明只有拥有 application.create 资源的角色才能进行创建操作.

    统一 UI 按钮与 API 操作的资源标识是权限设置的最佳实践.

    另一种方法是UI按钮与API操作使用不同的资源标识,再将API资源绑定到UI按钮,这种方式更复杂且容易出错.

    如果仅对 Web Api 进行访问控制, 可以使用API资源, 资源标识为 Api 地址,不需要在每个控制器打上 [Acl] 特性,Util 还提供了Acl过滤器,可以全局启用访问控制.

    拥有细粒度操作资源的角色必须拥有查看资源.

    对于本例,如果需要访问 CreateAsync 操作,Asp.Net Core首先验证 application.view 资源是否能访问,如果通过才会继续验证 application.create 资源.

  • 授予权限

    一旦创建操作资源,并在 UI 和 API 进行了Acl设置,就可以为角色授权.

    数据迁移默认创建了两个角色,admin 和 test,并已将用户 test 关联到 test 角色,以及将用户 admin 关联到 admin角色.

    点击左侧 角色 菜单,打开角色列表.

    角色列表中点击 test 角色 权限设置 链接,如下所示.

    Util应用框架快速入门(5) - 权限入门

    弹出 角色权限设置对话框,如下所示.

    Util应用框架快速入门(5) - 权限入门

    默认 test 角色只能查看应用程序.

验证操作权限

下面来验证权限控制是否生效.

验证 UI 按钮权限

鼠标移到右上方头像,弹出菜单点击 退出登录 链接.

Util应用框架快速入门(5) - 权限入门

使用 test 用户登录,密码 test .

可以看到,只有一个应用程序菜单,并且操作按钮也消失了.

Util应用框架快速入门(5) - 权限入门

为 test 角色授予创建权限

退出登录,使用 admin 用户登录.

打开 test 角色 权限设置 窗口,勾选 授予 应用程序创建 复选框,点击确定按钮,如下所示.

Util应用框架快速入门(5) - 权限入门

还支持拒绝权限,如果用户的某个角色拥有拒绝资源,则无法访问该资源.

退出登录,使用 test 用户登录.

打开应用程序页面,可以看到创建按钮已经显示出来.

Util应用框架快速入门(5) - 权限入门

验证 Api 权限

打开 Swagger ,之前已经测试过创建应用程序 API 接口无法访问,下面再来试试.

Util应用框架快速入门(5) - 权限入门

提交下面的数据.

{   "code": "test",   "name": "test",   "enabled": true } 

提交返回操作成功消息,说明权限设置生效.

Util应用框架快速入门(5) - 权限入门

全局关闭访问控制

一旦 Web Api 控制器添加了 [Acl] 特性,权限就已经启用.

对于某些场景可能相当麻烦,比如 Web Api 集成测试.

权限是由 Identity Server 提供的,你的集成测试需要从 Identity Server 获取令牌,这造成了不必要的负担.

Util应用框架支持全局关闭访问控制,如下所示.

.AddAcl( t => t.AllowAnonymous = true ) 

AddAcl 配置 Util访问控制相关的服务依赖,AllowAnonymous让所有添加了 [Acl] 的方法跳过权限检测,无需登录,无需授权.

发表评论

评论已关闭。

相关文章