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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM