转载

ABP理论学习之授权(Authorization)

返回总目录

本篇目录

  • 介绍
  • 定义权限
  • 检查权限
    • 使用AbpAuthorize特性
    • 使用IPermissionChecker
    • Razor视图
    • 客户端(Javascript)
  • 权限管理者

几乎所有的企业应用都在不同程度使用了授权。授权的目的在于检查是否允许用户在应用程序中执行特定的操作。ABP定义了一个 基于权限的 基础设施来实现授权。

关于IPermissionChecker

授权系统使用了 IPermissionChecker 来检查权限。虽然你可以用自己的方式实现该接口,但是它已完全实现在了 module-zero 项目中。如果没有实现该接口,那么系统会默认使用NullPermissionChecker将所有的权限授予给每个人。

定义权限

一个唯一的权限是为需要授权的每个操作定义的。我们应该在使用权限之前定义一个权限。ABP的设计是模块化的,因此不同的模块可以有不同的权限。为了定义模块的权限,应该创建一个派生自 AuthorizationProvider(以下翻译为授权提供者) 的类。一个授权提供者的例子如下所示:

public class MyAuthorizationProvider : AuthorizationProvider {     public override void SetPermissions(IPermissionDefinitionContext context)     {         var administration = context.CreatePermission("Administration");          var userManagement = administration.CreateChildPermission("Administration.UserManagement");         userManagement.CreateChildPermission("Administration.UserManagement.CreateUser");          var roleManagement = administration.CreateChildPermission("Administration.RoleManagement");     } } 

IPermissionDefinitionContext有创建和获取权限的方法。

一个权限定义了一些属性:

  • Name: 系统中 唯一的 名字。最好为权限的名字定义一个const字符串而不是变量字符串。我们偏向使用“.”符号用于有层次的名字,但这不是强制的。你可以设置任何你喜欢的名字,唯一的一点是保证它必须是唯一的。
  • DisplayName: 用于以后在UI上显示权限的本地化字符串。
  • Description: 用于以后在UI上显示权限定义的本地化字符串。
  • IsGrantedByDefault: 表示该权限是否授予给所有登录的用户,除非该权限显示禁止未授予给用户。该值一般默认为false。
  • MultiTenancySides: 对于多租户应用,租户或者租主可以使用同一个权限。这是一个 Flags 枚举,因此一个权限可以用于租户和租主。
  • dependedFeature: 可以用于声明一个功能的依赖。因此,只有功能依赖满足了,该权限才会被授予。

一个权限可以有父权限和子权限。虽然这不会影响权限检查,但是在UI上组合权限有所帮助。

当创建了授权提供者之后,我们应该在模块的PreIntialize方法中注册它:

Configuration.Authorization.Providers.Add<MyAuthorizationProvider>(); 

因为授权提供者会自动地注册到依赖注入系统中,所以,授权提供者通过一些其他资源,可以注入任何依赖(比如仓储)来生成权限定义。

检查权限

使用AbpAuthorize特性

AbpAuthorize(MVC控制器是AbpMvcAuthorize,Web API控制器是AbpApiAuthorize)是最简单也是最普通的检查权限的方式。思考一下下面的应用服务方法:

[AbpAuthorize("Administration.UserManagement.CreateUser")] public void CreateUser(CreateUserInput input) {     //如果一个用户没有被授予 "Administration.UserManagement.CreateUser" 权限,那么ta就不能执行此方法 } 

AbpAuthorize特性也会检查当前的用户是否已经登录(使用 IAbpSession.UserId )。因此,如果我们为一个方法声明了AbpAuthorize,它至少会检查登录情况:

[AbpAuthorize] public void SomeMethod(SomeMethodInput input) {     //如果用户没有登录,那么ta就不能执行此方法 }  

AbpAuthorize特性需要注意的地方

ABP对于授权使用了强大的动态方法拦截(interception)。因此,使用AbpAuthorize特性有一些限制:

  • 不能用于私有方法。
  • 不能用于静态方法。
  • 不能用于非注入类的方法(我们必须要使用依赖注入)。

此外,

  • 可以用于任何 public 方法,如果该方法是通过接口调用的(比如应用服务通过接口使用)。
  • 方法应该是 virtual 的,如果它是从类的引用直接调用的(比如ASP.Net MVC或者Web API的控制器)。
  • 如果方法是 protected 的,那么它应该是 virtual 的。

注意:AbpAuthorize特性有三个:

在应用服务中(应用层),我们使用 Abp.Authorization.AbpAuthorize 类。

在MVC控制器中(Web层),我们使用 Abp.Web.Mvc.Authorization.AbpMvcAuthorize 类。

在ASP.NET Web API中,我们使用 Abp.WebApi.Authorization.AbpApiAuthorize 特性。

这个差异来自继承。在MVC端,派生自MVC自己的Authorize类。在Web API端,它派生自Web API的Authorize类。因此,它已经很好地集成到了MVC和Web API。但是在应用层,它完全是ABP自己的实现而没有扩展任何类。

使用IPermissionChecker

虽然AbpAuthorize特性对于大多数情况相当够用了,但是肯定存在我们会在一个方法体内检查权限的情况。我们可以注入并使用 IPermissionChecker ,如下面的例子所示:

public void CreateUser(CreateOrUpdateUserInput input) {     if (!PermissionChecker.IsGranted("Administration.UserManagement.CreateUser"))     {         throw new AbpAuthorizationException("You are not authorized to create user!");     }          //如果一个用户没有"Administration.UserManagement.CreateUser" 权限,那么ta不能到达该点。 } 

当然,你可以编写任何逻辑代码,因为 IsGranted 仅仅返回true或者false(也有Async版本)。如果你只是检查一个权限然后抛出一个如上所示的异常,那么你可以使用 Authorize 方法:

public void CreateUser(CreateOrUpdateUserInput input) {     PermissionChecker.Authorize("Administration.UserManagement.CreateUser");      //如果一个用户没有"Administration.UserManagement.CreateUser" 权限,那么ta不能到达该点。 } 

因为授权一般在应用层实现,所以 ApplicationService 基类注入并定义了PermissionChecker属性。这样,权限检查者不需要在应用服务类中注入就可以使用了。

Razor视图

视图基类定义了IsGranted方法来检查当前用户是否具有权限。因此,我们可以有条件地渲染该视图。例子:

@if (IsGranted("Administration.UserManagement.CreateUser")) {     <button id="CreateNewUserButton" class="btn btn-primary"><i class="fa fa-plus"></i> @L("CreateNewUser")</button> } 

客户端(Javascript)

在客户端,我们可以使用定义在 abp.auth 命名空间下的API。在大多数情况,我们需要检查当前的用户是否具有特定的权限(使用权限名字)。例子:

abp.auth.hasPermission('Administration.UserManagement.CreateUser'); 

你也可以使用 abp.auth.grantedPermissions 来获得所有授权的权限或者使用 abp.auth.allPermissions 来所有应用中可用的权限名。

权限管理者

我们可能需要定义权限。这时可以注入并使用 IPermissionManager

正文到此结束
Loading...