zoukankan      html  css  js  c++  java
  • ABP理论学习之授权(Authorization)

    返回总目录


    本篇目录

    介绍###

    几乎所有的企业应用都在不同程度使用了授权。授权的目的在于检查是否允许用户在应用程序中执行特定的操作。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来获取所有应用中可用的权限名。

    注意:自ABP 0.7.8版本开始,将javascript端的abp.auth.hasPermission更名为abp.auth.isGranted。hasPermission已经过时了。在新的项目中不要使用abp.auth.hasPermission

    权限管理者###

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

  • 相关阅读:
    stutas2配置action
    Struts2 第一个入门小案例
    spring与mybati整合方法
    spring事务隔离级别以及脏读 不可重复读 幻影读
    socket编程基础
    ajax随笔
    多线程基础
    Mybatis中collection与association的区别
    Guideline 2.3.1
    苹果手机 apple pay 一不小心支付购买了自己不要的服务
  • 原文地址:https://www.cnblogs.com/farb/p/ABPAuthorization.html
Copyright © 2011-2022 走看看