Contents

.Net Core Identity 角色管理

我們常常開發程式帳號登入,通常還會做權限功能,這邊很常開發會用角色(Role)這個東西,去做權限劃分,有時候我們需要更細,但系統不一定會做到這樣,但有沒有常見規劃權限方法。

常見權限方法

之前看到 RBAC這個名詞是在 Kubernetes 那邊看到,那時候還沒有深入了解設計理念,最近在看 .Net Core Identity 文章,看到這個框架有做這個非常方便東西,可以瞭解這個是什麼用途。

RBAC

以角色為基礎的存取控制[1][2](英語:Role-based access control,RBAC),是資訊安全領域中,一種較新且廣為使用的存取控制機制,其不同於強制存取控制以及自由選定存取控制[3]直接賦予使用者權限,而是將權限賦予角色。
以角色為基礎的存取控制模型是一套較強制存取控制以及自由選定存取控制更為中性且更具靈活性的存取控制技術。
參考: 以角色為基礎的存取控制 - 維基百科,自由的百科全書

更多可以看Role-Based Access Control (RBAC). 作者:銀伶 | by I.S. BLOG | Medium

CBAC

Claim 動詞則有宣稱,聲稱, 主張, 自稱, 指控, 認領,索賠等意思
名詞則有權利 , 要求權和聲明等

Claims-based 則是一個專有詞,代表基於聲明的認證(Claims-based identity)
用於Google,Facebook,Microsoft等都有此機制的概念導入

參考: ASP.NET MVC第014天_ASP.NET Identity使用筆記_使用者登入_Claims-based identity理解

網路上比較少介紹 CBAC,簡單它可以分更細權限,這邊帳號可以設定特定角色,但是有時候有例外,像是帳號想把它加上權限上去,透過CBAC就可以設定。但注意 Claim不是只有套用在帳號上面,也可以套用帳號上面。

建立角色

GIT: 建立角色 · malagege/NetCoreAuthSample@578bdd6

RoleManager 可以簡單對 Role 做 CRUD。會新增到 AspNetRoles 資料表。

  1. Controller 注入 RoleManager
  2. 建立ModelView
  3. Controller 建立Role
  4. View 設定

簡單步驟跟之前差不多

角色清單

_roleManager.Roles 抓出所有角色資料。

GIT: 角色列表 · malagege/NetCoreAuthSample@3fa29c7

Controller,View 那些不寫了,這邊還順便複習View 要怎麼寫。公司目前後端很少寫 View。
主要同一個 Action 有 Get, Post 方法,所以<from>就不需要特別設定 asp-action,這個設計值得效仿。

編輯角色

GIT:編輯角色_修改名稱 · malagege/NetCoreAuthSample@6f56c8b

同上

角色下使用者清單

GIT: 角色顯示使用者清單 · malagege/NetCoreAuthSample@d913d9d

Model List 屬性初始化

GIT:初始化使用者清單 · malagege/NetCoreAuthSample@4ab3828

常常用List遇到 NullPointerException 問題,這邊我們用這個技巧可以避免。

角色下添加/刪除使用者

GIT: 使用者添加角色 · malagege/NetCoreAuthSample@2a21605

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
                // ***重點***  Start
                // 選擇跟查詢結果不一樣,更改資料
                bool isInRole = await _userManager.IsInRoleAsync(user, role.Name);
                if (model[i].IsSelected && !(isInRole))
                {
                    result = await _userManager.AddToRoleAsync(user, role.Name);   // 使用者角色新增 role.Name
                }
                else if (!model[i].IsSelected && (isInRole))
                { 
                    result = await _userManager.RemoveFromRoleAsync(user, role.Name);   // 使用者角色移除 role.Name
                }
                else
                {
                    continue;     //與資料庫一樣不做處理
                }

                if (result.Succeeded)
                {
                    if(i < (model.Count - 1))  //簡單來說,第一次和中間次數跑 continue 執行最後一次會跑 else 內容
                    {
                        continue;
                    }
                    else
                    {
                        return RedirectToAction("EditRole", new { Id = roleId });
                    }
                }
                // ***重點***  End

await _userManager.AddToRoleAsync(user, role.Name);ㄏ(user, role.Name); 可以讓使用者加入角色,注意使用者和角色資料表示多對多的。我們知道資料表多對多是要用到三個資料表。

資料表

我們操作這個範例,可以看到我們用_userManager.AddToRoleAsync_userManager.AddToRoleAsync控制這些表資料。.Net Core Identity 不只下面這些表,後續整理相關筆記會特別畫 ERD 關聯。

erDiagram AspNetUsers }|..|{ AspNetRoles : has

多對多關係是用三張表去做關聯

erDiagram AspNetUsers ||..|{ AspNetUserRoles : has AspNetUserRoles }|..|| AspNetRoles : own AspNetUsers{ string id string UserName string Email } AspNetUserRoles{ string UserId string RoleId } AspNetRoles{ string Id string Name string NormalizeName }

思考問題

  1. 效能問題(n+1)
    用Users跑 for迴圈,不知道這樣設定資料是不是好事?假如users到一萬筆可能跑迴圈也是不好的事情,所以這邊可以思考從使用者那邊設定角色是不是好的解決方法

  2. 執行發生錯誤,能否rollback
    我們使用 EF Core都會用到 savechanges()去判斷是否要做commit,這邊我猜測 context應該有跟savechanges做 commit一樣動作,但我現階段先不測試。

  3. UserManager,RoleManager 設計模式,回傳XXXResult 物件
    上面我們看到有做 xxxResult,這部分針對 ModelState.AddError搭配使用還滿方便,平常寫 Service 很少寫這個物件,這個有空看看相關文章有沒有這一層物件設計模式處理。

  4. Net Core Identity 資料表關係
    這章節只用到這三張表,我有偷看後續表,針對使用上 Net Core Identity 會異動那些資料表資料,我覺得這是很重要的事情。

    彩蛋

    [ASP.NET MVC] 使用CLK.AspNet.Identity提供以角色為基礎的存取控制(RBAC) | 昏睡領域 - 點部落