1. 程式人生 > >ABP module-zero +AdminLTE+Bootstrap Table+jQuery許可權管理系統第十三節--RBAC模式及ABP許可權管理(附贈福利)

ABP module-zero +AdminLTE+Bootstrap Table+jQuery許可權管理系統第十三節--RBAC模式及ABP許可權管理(附贈福利)

角色訪問控制(RBAC)

角色訪問控制(RBAC)應該是目前用得最多也是關注最多的許可權管理模型了。
許可權(Permission)與角色(Role)相關聯,使用者(User)通過成為適當角色的成員而得到這些角色的許可權。這就極大地簡化了許可權的管理。
RBAC引入了角色(Role)概念,目的應該是解耦了PermissionUser之間的關係,直接授權給Role,而不是直接授權給使用者,或者使用者組。
基於角色的訪問控制方法(RBAC)的顯著的兩大特徵是:

  1. 由於角色/許可權之間的變化比角色/使用者關係之間的變化相對要慢得多,減小了授權管理的複雜性,降低管理開銷。
  2. 靈活地支援企業的安全策略,並對企業的變化有很大的伸縮性。
    RBAC支援三個著名的安全原則:最小許可權原則,責任分離原則和資料抽象原則。
    (1)最小許可權原則之所以被RBAC所支援,是因為RBAC可以將其角色配置成其完成任務所需要的最小的許可權集。
    (2)責任分離原則可以通過呼叫相互獨立互斥的角色來共同完成敏感的任務而體現,比如要求一個計帳員和財務管理員共參與同一
    過帳

    (3)資料抽象可以通過許可權的抽象來體現,如財務操作用借款、存款等抽象許可權,而不用作業系統提供的典型的讀、寫、執行許可權。然而這些原則必須通過RBAC各部件的詳細配置才能得以體現。

RBAC結構

1.png

RBAC認為許可權授權實際上是Who、What、How的問題。在RBAC模型中,who、what、how構成了訪問許可權三元組,也就是“Who對What(Which)進行How的操作”。

  • Who:許可權的擁用者或主體(如Principal、User、Group、Role、Actor等等)
  • What:許可權針對的物件或資源(Resource、Class)。
  • How:具體的許可權(Privilege,正向授權與負向授權)。
  • Operator:操作。表明對What的How操作。也就是Privilege+Resource
  • Role:角色,一定數量的許可權的集合。許可權分配的單位與載體,目的是隔離User與Privilege的邏輯關係.
  • Group:使用者組,許可權分配的單位與載體。許可權不考慮分配給特定的使用者而給組。組可以包括組(以實現許可權的繼承),也可以包含使用者,組內使用者繼承組的許可權。User與Group是多對多的關係。Group可以層次化,以滿足不同層級許可權控制的要求。
  1. RBAC的關注點在於Role和User, Permission的關係。稱為User assignment(UA)Permission assignment(PA)
    .關係的左右兩邊都是Many-to-Many關係。就是user可以有多個role,role可以包括多個user。
  2. 凡是用過RDBMS都知道,n:m 的關係需要一箇中間表來儲存兩個表的關係。這UA和PA就相當於中間表。事實上,整個RBAC都是基於關係模型。
  3. Session在RBAC中是比較隱晦的一個元素。標準上說:每個Session是一個對映,一個使用者到多個role的對映。當一個使用者啟用他所有角色的一個子集的時候,建立一個session。每個Session和單個的user關聯,並且每個User可以關聯到一或多個Session.
  4. 在RBAC系統中,User實際上是在扮演角色(Role),可以用Actor來取代User,這個想法來自於Business Modeling With UML一書Actor-Role模式。考慮到多人可以有相同許可權,RBAC引入了Group的概念。Group同樣也看作是Actor。而User的概念就具象到一個人。
    這裡的Group和GBAC(Group-Based Access Control)中的
  5. Group(組)不同。GBAC多用於作業系統中。其中的Group直接和許可權相關聯,實際上RBAC也借鑑了一些GBAC的概念。
  6. Group和User都和組織機構有關,但不是組織機構。二者在概念上是不同的。組織機構是物理存在的公司結構的抽象模型,包括部門,人,職位等等,而許可權模型是對抽象概念描述。組織結構一般用Martin fowler的Party或責任模式來建模。
  7. Party模式中的Person和User的關係,是每個Person可以對應到一個User,但可能不是所有的User都有對應的Person。Party中的部門Department或組織Organization,都可以對應到Group。反之Group未必對應一個實際的機構。例如,可以有副經理這個Group,這是多人有相同職責。
  8. 引入Group這個概念,除了用來解決多人相同角色問題外,還用以解決組織機構的另一種授權問題:例如,A部門的新聞我希望所有的A部門的人都能看。有了這樣一個A部門對應的Group,就可直接授權給這個Group。

ABP許可權管理

首先ABP許可權管理也是基於RBAC的。
在 RBAC之中,包含使用者users(USERS)、角色roles(ROLES)、目標objects(OBS)、操作operations(OPS)、許可權permissions(PRMS)五個基本資料元素,許可權被賦予角色,而不是使用者,當一個角色被指定給一個使用者時,此使用者就擁有了該角色所包含的許可權。會話sessions是使用者與啟用的角色集合之間的對映。
然後我們來看一下一開始就生成的AbpPermissions表。
2.png

我們可以看到一個許可權(AbpPermissions)有以下屬性:
Name:系統範圍內的唯一名字。把它定義為一個字串常量是個不錯的注意。我們傾向於將“.”分割不同的層級,但並不要求這麼做。你可以設定你任何喜歡的名字。唯一的規則就是這個名字必須是唯一的。

  • Display Name:使用一個本地化的字串去顯示許可權到UI。
  • Description:和Display Name類似。
  • IsGrantedByDefault:此許可權是否授權給(已登陸)所有使用者,除非顯示指定。通常設定為False(預設值)。
  • MultiTenancySides:對租戶應用程式,一個許可權可以基於租戶或者主機(原文:host)。這是個列舉標識,因此許可權可以應用於不同方面。一個許可權可以有父許可權和子許可權。

定義許可權

前面幾篇文章,我們已經完成了使用者詳情列表的增刪改查。
這裡我們來給他們加上許可權,首先,在module-zero專案中已經完整實現了。我們先看下預設已經存在的程式碼。

  public class ABPCMSAuthorizationProvider : AuthorizationProvider
    {
        public override void SetPermissions(IPermissionDefinitionContext context)
        {
            context.CreatePermission(PermissionNames.Pages_Users, L("Users"));
            context.CreatePermission(PermissionNames.Pages_Roles, L("Roles"));
            context.CreatePermission(PermissionNames.Pages_Tenants, L("Tenants"), multiTenancySides: MultiTenancySides.Host);
        }
        private static ILocalizableString L(string name)
        {
            return new LocalizableString(name, ABPCMSConsts.LocalizationSourceName);
        }
    }

我們仿照這段程式碼,新建一個類UserInfoAuthorizationProvider,繼承自AuthorizationProvider,看下程式碼:

   public class UserInfoAuthorizationProvider: AuthorizationProvider
    {
        public override void SetPermissions(IPermissionDefinitionContext context)
        {

            var pages = context.GetPermissionOrNull(PermissionNames.Pages);
            if (pages == null)
                pages = context.CreatePermission(PermissionNames.Pages, L("Pages"));


            var UserInfos= pages.CreateChildPermission(PermissionNames.Pages_UserInfos, L("UserInfos"));
            UserInfos.CreateChildPermission(PermissionNames.Pages_UserInfos_Create, L("UserInfosCreate"));
            UserInfos.CreateChildPermission(PermissionNames.Pages_UserInfos_Delete, L("UserInfosDelete"));
            UserInfos.CreateChildPermission(PermissionNames.Pages_UserInfos_Update, L("UserInfosUpdate"));
        }

        private static ILocalizableString L(string name)
        {
            return new LocalizableString(name, ABPCMSConsts.LocalizationSourceName);
        }
    }

然後再PermissionNames中依樣新增如下常量。

  public static class PermissionNames
    {
        public const string Pages_Tenants = "Pages.Tenants";

        public const string Pages_Users = "Pages.Users";

        public const string Pages_Roles = "Pages.Roles";


        public const string Pages = "Pages";

        public const string Pages_UserInfos = "Pages.UserInfos";

        public const string Pages_UserInfos_Create = "Pages.UserInfo.Create";

        public const string Pages_UserInfos_Delete = "Pages.UserInfo.Delete";

        public const string Pages_UserInfos_Update = "Pages.UserInfo.Update";
    }

定位到ABPCMSCoreModule.cs,這裡已經有關於 Configuration.Authorization.Providers.Add<ABPCMSAuthorizationProvider>();
我們在他的下面補上我們自己的類。
Configuration.Authorization.Providers.Add<UserInfoAuthorizationProvider>();

給admin賦值

定位到HostRoleAndUserCreatorTenantRoleAndUserBuilder
然後手動在下面新增上如下程式碼。

   //Grant all tenant permissions
                var permissions = PermissionFinder
                    .GetAllPermissions(new ABPCMSAuthorizationProvider())
                    .Where(p => p.MultiTenancySides.HasFlag(MultiTenancySides.Host))
                    .ToList();

在這段程式碼之下,新增如下程式碼。

     //將UserInfoAuthorizationProvider相關Permission賦予給Admin
                var UserInfoAuthorization =
                    PermissionFinder.GetAllPermissions(new UserInfoAuthorizationProvider()).ToList();
                permissions.AddRange(UserInfoAuthorization);

刪除資料庫執行命令並生成資料庫

有了上面的基礎,我們先刪除資料庫,在生成資料庫,有人說這裡為什麼要刪除資料庫,因為在在ABP模板專案中暫未提供使用者角色許可權管理功能,但在AbpZero中提供了該功能,支援按使用者或角色賦予許可權,在資料庫初始化的時候,將許可權賦給Admin。我們已經建立了資料庫,所以要刪除資料庫重新初始化。
5.png
執行update-database -Verbose命令,於是生成資料庫如下。

6.png

有了資料,admin使用者已經賦予了許可權,自然不需要我們去管,但是如果我們切換使用者進來,就沒有許可權,我們怎麼出給他加上許可權呢。
我們直接在控制方法上新增上標籤[AbpAuthorize(PermissionNames.Pages_UserInfos)]就可以了

        [AbpAuthorize(PermissionNames.Pages_UserInfos)]
        [HttpGet]
        [DontWrapResult]

        public async Task<ActionResult> GetUserInfo()
        {
            string pageNumber = string.IsNullOrWhiteSpace(Request["pageNumber"]) ? "0" : Request["pageNumber"];
            string pageSize = string.IsNullOrWhiteSpace(Request["pageSize"]) ? "20" : Request["pageSize"];
            var users = (await _userAppService.GetAll(new PagedResultRequestDto { MaxResultCount = int.MaxValue })).Items;
            var  Userlist = users.Skip(int.Parse(pageNumber) * int.Parse(pageSize)).Take(int.Parse(pageSize)).ToList();
            int totaldata = Userlist.Count();
            var result = new { total = 10, rows = Userlist };
            return Json(result, JsonRequestBehavior.AllowGet);
        }

同時這裡是用區別的。

  1. 在應用服務層中我們直接直接使用[AbpAuthorize]特性,
  2. 但在MVC控制器中使用[AbpMvcAuthorize]特性,
  3. Web API控制器中使用[AbpApiAuthorize]
    AbpAuthorize屬性說明(AbpAuthorize attribute notes)
    Abp使用動態方法攔截進行許可權驗證。因此,使用AbpAuthorize特性的方法會有些限制。如下:
  • 不能應用於私有(private)方法
  • 不能應用於靜態(static)方法
  • 不能應用於非注入(non-injected)類(我們必須用依賴注入)。
    此外,
  • AbpAuthorize特性可以應用於任何的Public方法,如果此方法被介面呼叫(比如在Application Services中通過介面呼叫)
  • 方法是虛(virtual)方法,如果此方法直接被類引用進行呼叫(像是ASP.NET MVC 或 Web API 的控制器)。
  • 方式是虛(virtual)方法,如果此方法是protected
    注意:有三種AbpAuthorize 特性:
    在應用程式服務中(application layer),我們使用Abp.Authorization.AbpAuthorize
  • 在MVC控制器(web layer)中,我們使用Abp.Web.Mvc.Authorization.AbpMvcAuthorize
  • 在ASP.NET Web API,我們使用 Abp.WebApi.Authorization.AbpApiAuthorize
    這三個類繼承自不同的地方。
  • 在MVC中,它繼承自MVC自己的Abp.Web.Mvc.Authorization.AbpMvcAuthorize類。
  • 在Web API,它繼承自Web API 的Abp.WebApi.Authorization.AbpApiAuthorize類。因此,它最好是繼承到MVC和Web API中。
  • 但是,在Application 層,它完全是由Abp自己實現沒有擴充套件子任何類。

IPermissionChecker及前端授權

  1. AbpAuthorize適用於大部分的情況,但是某些情況下,我們還是需要自己在方法體裡進行許可權驗證。我們可以注入和使用IPermissionChecker物件。如下邊的程式碼所示:
public void CreateUser(CreateOrUpdateUserInput input)
{
    if (!PermissionChecker.IsGranted("Administration.UserManagement.CreateUser"))
    {
        throw new AbpAuthorizationException("You are not authorized to create user!");
    }

    //A user can not reach this point if he is not granted for "Administration.UserManagement.CreateUser" permission.
}

因為授權一般在應用服務層中進行,所以ABP預設在ApplicationService基類注入並定義了PermissionChecker屬性。這樣,在應用服務層就可以直接使用PermissionChecker屬性進行許可權檢查。如下面的程式碼:


        protected override async Task<User> GetEntityByIdAsync(long id)
        {
            bool UserInfos = PermissionChecker.IsGranted(PermissionNames.Pages_UserInfos);
            //如果當前人員沒有許可權,則丟擲異常
            if (!UserInfos)
            {
                throw new AbpAuthorizationException("沒有許可權!");
            }
            var user = Repository.GetAllIncluding(x => x.Roles).FirstOrDefault(x => x.Id == id);
            return await Task.FromResult(user);
        }
  1. 前臺html ,javascript頁面中加入以前程式碼即可過濾許可權:
@if (IsGranted(PermissionNames.Pages_UserInfos))
{
 //業務程式碼
}
  1. 我們可以使用定義在abp.auth名稱空間下的API.
    abp.auth.hasPermission('PermissionNames.Pages_UserInfos);
    你也可以使用abp.auth.grantedPermissions來獲得所有授權的許可權或者使用 abp.auth.allPermissions來獲取所有應用中可用的許可權名。

注意:自ABP 0.7.8版本開始,將javascript端的abp.auth.hasPermission更名為abp.auth.isGranted。hasPermission已經過時了。在新的專案中不要使用abp.auth.hasPermission。

總結

其實ABP module-zero中的許可權管理讓人痛苦,如果我要去對AbpPermissions表等其他表進行增刪查改的時候,很痛苦,或者給要admin賦值的時候不可能每次都刪資料庫去實現,雖然在abp zero已經實現。我覺得最好的方式是不要module-zero那套東西,一切都自己去建立一套RBAC。
送上本文原始碼:https://github.com/Jimmey-Jiang/ABP-ASP.NET-Boilerplate-Project-CMS。

最後送上福利。

github地址: https://github.com/Jimmey-Jiang/WY.MVC.RMS
一套完整許可權管理系統,codefirst,直接生成資料庫可用。
12.png

本章專案圖

 1.png

2.png

3.png

相關推薦

ABP module-zero +AdminLTE+Bootstrap Table+jQuery許可權管理系統三節--RBAC模式ABP許可權管理福利

角色訪問控制(RBAC) 角色訪問控制(RBAC)應該是目前用得最多也是關注最多的許可權管理模型了。 許可權(Permission)與角色(Role)相關聯,使用者(User)通過成為適當角色的成員而得到這些角色的許可權。這就極大地簡化了許可權的管理。 RBAC引入了角色(Role)概念,目的應該是解耦了P

ABP module-zero +AdminLTE+Bootstrap Table+jQuery許可權管理系統四節--後臺工作者HangFire與ABP框架Abp.Hangfire擴充套件

HangFire與Quartz.NET相比主要是HangFire的內建提供整合化的控制檯,方便後臺檢視及監控,對於大家來說,比較方便。 HangFire是什麼 Hangfire是一個開源框架(.NET任務排程框架),可以幫助您建立,處理和管理您的後臺作業,處理你不希望放入請求處理管道的操作: 通知/通訊;

ABP module-zero +AdminLTE+Bootstrap Table+jQuery許可權管理系統七節--Quartz與ABP框架Abp.Quartz擴充套件

Quartz簡介 Quartz.NET是一個開源的作業排程框架,是 OpenSymphony 的 Quartz API 的.NET移植,它用C#寫成,可用於winform和asp.net應用中。它提供了巨大的靈活性而不犧牲簡單性。你能夠用它來為執行一個作業而建立簡單的或複雜的排程。它有很多特徵,如:資料庫支

ABP module-zero +AdminLTE+Bootstrap Table+jQuery許可權管理系統六節--SignalR與ABP框架Abp.Web.SignalR擴充套件

SignalR簡介 SignalR是什麼? ASP.NET SignalR 是為 ASP.NET 開發人員提供的一個庫,可以簡化開發人員將實時 Web 功能新增到應用程式的過程。實時 Web 功能是指這樣一種功能:當所連線的客戶端變得可用時伺服器程式碼可以立即向其推送內容,而不是讓伺服器等待客戶端請求新的資

ABP module-zero +AdminLTE+Bootstrap Table+jQuery許可權管理系統二節--小結,Bootstrap Table之角色管理以及module-zero角色管理

寫在前面的話           很多人說ABP不適合高併發大型,有一定的道理,但是我覺得還是可以的,就看架構師的能力了,我之前公司就是ABP絕對百萬資料級專案,是一個線上教育網站,涉及到平臺,學院,院系,班級,課程,學生等,一個平臺多少大學,一個大學多少院系,一個院系多少班級多少課程,其負責程度一

ABP module-zero +AdminLTE+Bootstrap Table+jQuery許可權管理系統五節--快取小結與ABP框架專案中 Redis Cache的實現

快取 為什麼要用快取 為什麼要用快取呢,說快取之前先說使用快取的優點。 減少寄宿伺服器的往返呼叫(round-trips)。 如果快取在客戶端或是代理,將減少對伺服器的請求,減少頻寬。 減少對資料庫伺服器的往返呼叫(round-trips)。 當內容快取在web伺服器,能夠減輕對資料庫的請求。 減少網路

ABP module-zero +AdminLTE+Bootstrap Table+jQuery權限管理系統二節--小結,Bootstrap Table之角色管理

增刪 習慣 etc 根據 很好 這不 update 必須 virtual 返回總目錄:ABP+AdminLTE+Bootstrap Table權限管理系統一期 很多人說ABP不適合高並發大型,有一定的道理,但是我覺得還是可以的,就看架構師的能

ABP+AdminLTE+Bootstrap Table許可權管理系統一節--Bootstrap Table使用者管理列表以及Module Zero之使用者管理

   使用者實體       使用者實體代表應用的一個使用者,它派生自AbpUser類,如下所示: public class User : AbpUser<Tenant, User> { //add your own user properties here

ABP+AdminLTE+Bootstrap Table許可權管理系統七節--登入邏輯幾種abp封裝的Javascript函式庫

        簡介        經過前幾節,我們已經解決資料庫,模型,DTO,控制器和注入等問題.那麼再來看一下登入邏輯.這裡算是前面幾節的一個初次試水. 首先我們資料庫已經有的相應的資料. 新增Login方法        模型和DTO已經建好,所以我們直接在服務層新增Login方法就可

ABP+AdminLTE+Bootstrap Table許可權管理系統節--AdminLTE模板選單處理

 AdminLTE選單       上節我們把佈局頁,也有的臨時的選單,但是選單不是應該動態載入的麼?,所以我們這節來寫選單.首先我們看一下AdminLTE原始碼裡面的選單以及結構. <aside class="main-sidebar"> <!--

ABP+AdminLTE+Bootstrap Table許可權管理系統第一節--使用ASP.NET Boilerplate模板建立解決方案

ABP+AdminLTE+Bootstrap Table許可權管理系統一期 Github:https://github.com/Jimmey-Jiang/ABP-ASP.NET-Boilerplate-Project-CMS 前往部落格園總目錄

ABP+AdminLTE+Bootstrap Table許可權管理系統一期

 初衷    學而時習之,不亦說乎,溫顧溫知新,可以為師矣.           看懂遠不如動手去做,動手做才能發現很多自己不懂的問題,不斷的反思和總結,“樂於分享是一種境界的突破”。" 分享是很有意思,也是可以鍛鍊人的。 分享意味著自我的不斷淨化提升,不給自己後退的餘地。為什麼這麼說呢?因為:一,分

ABP+AdminLTE+Bootstrap Table許可權管理系統九節--AdminLTE引入模板頁和佈局和選單

 AdminLTE    首先去官網下載包下來,然後引入專案.   然後我們在web層新增區域Admin以及Common,關於AdminLTE的地址我們放在Common路勁下面.   在Common下新增LayoutController控制器. Layout 這裡選單我們先不管,在後

ABP+AdminLTE+Bootstrap Table許可權管理系統四節--倉儲,服務,服務介面依賴注入

AbpModule      在ABP框架中,倉儲,服務,這塊算是最為重要一塊之一了.ABP框架提供了建立和組裝模組的基礎,一個模組能夠依賴於另一個模組,一個程式集可看成一個模組, 一個模組可以通過一個類來定義這個模組,而給定義這個類要繼承自已經瘋轉好的AbpModule..net通過反射來獲取這些程

ABP+AdminLTE+Bootstrap Table許可權管理系統三節--abp分層體系,實體相關ABP模組系統

ABP模組系統  說了這麼久,還沒有詳細說到abp框架,abp其實基於DDD(領域驅動設計)原則的細看分層如下: 再看我們專案解決方案如下: JCmsErp.Application,應用層:進行展現層與領域層之間的協調,協調業務物件來執行特定的應用程式的任務。它不包含業務邏輯,主要包

ABP+AdminLTE+Bootstrap Table許可權管理系統第二節--在ABP的基礎做資料庫指令碼處理

      第一點,上一篇文章中我們講到codefirst中一些問題包括如圖,codefirst在每次執行命令的時候會生成新的類,後來會越來越多。 1,codefirst在執行的資料庫遷移過程中產生了很多檔案,對於強迫症的我而言特別不爽,這些其實是可以不用生成的。 2,在codefirst實際

ABP+AdminLTE+Bootstrap Table許可權管理系統八節--ABP錯誤機制AbpSession相關

((ClaimsPrincipal)Thread.CurrentPrincipal).Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier);        需要獲取會話資訊則必須實現IAbpSession介面。雖然你

ABP+AdminLTE+Bootstrap Table許可權管理系統六節--abp控制器擴充套件json封裝

 一,控制器AbpController    說完了Swagger ui 我們再來說一下abp對控制器的處理和json的封裝.    首先我們定義一個控制器,在新增控制器的時候,控制器會自動繼承自AbpController,AbpController

Bootstrap Table 雙擊、單擊行獲取該行內容獲取全表的內容

Bootstrap Table 獲取單擊或雙擊的行內容 說明:看到這個應該就知道了bootstrap table的用法及如何使用了,所以下面的名稱就不介紹了 realTime_Table是表的id $("#realTime_Table").bootstr

企業管理系統前後端分離架構設計 系列一 許可權模型篇

前段時間分別用vue和react寫了兩個後臺管理系統的模板vue-quasar-admin和3YAdmin。兩個專案中都實現了基於RBAC的許可權控制。因為本職工作是後端開發,比較清楚許可權控制一個管理系統應該必須具備的核心功能,而且是可以做到通用的。打算寫寫關於管理系統前後端分離方面的文章,也是做一個知識的