ASP.NET MVC 基於角色的權限控制系統的示例教程


上一次在 .NET MVC 用戶權限管理示例教程中講解了ASP.NET MVC 通過AuthorizeAttribute類的OnAuthorization方法講解了粗粒度控制權限的方法,接下來講解基於角色的權限控制方法。

.NET MVC 用戶角色權限控制

基於角色的權限控制方法概述

基於角色的權限控制系統RBAC(Role Based Access Control)是目前最流行,也是最通用的權限控制系統。所謂基於角色的權限控制,就是將各個操作權限分組,每一個組就是一個角色,舉個例子:管理員擁有所有的權限,編輯就只擁有寫文章和發布文章的權限,這里的“管理員”和“編輯”就是一個角色——一系列操作權限的集合。我們只需要將某個角色賦予某個用戶那么這個用戶就擁有這個角色下的權限集合。

 

現在我們要做的就是通過把Controller下的每一個Action可以看作是一個權限,然后可以通過方法將每一個權限進行自定義的分組,從而創建一個角色,然后將角色與用戶對應起來。

基於角色的權限控制方法步驟

步驟一、新建一個RoleAuthorizeAttribute類

這個類可以拿到ControllerName和ActionName,這樣可以根據ControllerName和ActionName判斷是什么樣的操作,如下面的代碼

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Security;
 6 using System.Web.Mvc;
 7 using System.Web.Routing;
 8 
 9 namespace SampleMVCWebsite
10 {
11     public class RoleAuthorizeAttribute : AuthorizeAttribute
12     {
13         public override void OnAuthorization(AuthorizationContext filterContext)
14         {
15             var isAuth = false;
16             if (!filterContext.RequestContext.HttpContext.Request.IsAuthenticated)
17             {
18                 isAuth = false;
19             }
20             else
21             {
22                 if (filterContext.RequestContext.HttpContext.User.Identity != null)
23                 {
24                     var roleApi = new RoleApi();
25                     var actionDescriptor = filterContext.ActionDescriptor;
26                     var controllerDescriptor = actionDescriptor.ControllerDescriptor;
27                     var controller = controllerDescriptor.ControllerName;
28                     var action = actionDescriptor.ActionName;
29                     var ticket = (filterContext.RequestContext.HttpContext.User.Identity as FormsIdentity).Ticket;
30                     var role = roleApi.GetById(ticket.Version);
31                     if (role != null)
32                     {
33                         isAuth = role.Permissions.Any(x => x.Permission.Controller.ToLower() == controller.ToLower() && x.Permission.Action.ToLower() == action.ToLower());
34                     }
35                 }
36             }
37             if (!isAuth)
38             {
39                 filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "account", action = "login", returnUrl = filterContext.HttpContext.Request.Url, returnMessage = "您無權查看." }));
40                 return;
41             }
42             else
43             {
44                 base.OnAuthorization(filterContext);
45             }
46         }
47     }
48 }

 

 

其中RoleApi是角色對象管理的API,這里需要自己設置角色管理。上面的代碼中通過FilterContext的ActionDescriptor對象的ControllerDescriptor就可以獲取到ControllerName和ActionName。獲取到當前用戶的角色后,通過查看用戶的權限中是否包含了當前訪問的Controller中的方法,就能實現權限驗證。這里主要使用了ActionDescriptor和ControllerDescriptor,關於這兩個類的介紹可以參考MSDN官網。

PS:這里用Ticket的Version存儲RoleId。你也可以用其他方式。關於Ticket的知識可以參考微軟MSDN官方文檔,這里不再敖述。

步驟二、創建DescriptionAttribute類

這個類是繼承Attribute,為的是給Action方法打上描述標簽,如下面的代碼

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 
 6 namespace SampleMVCWebsite
 7 {
 8     /// <summary>
 9     /// Description Attribute
10     /// </summary>
11     public class DescriptionAttribute:Attribute
12     {
13         public string Name
14         {
15             set;
16             get;
17         }
18         public int No
19         {
20             set;
21             get;
22         }
23     }
24 }

 

 

Name和NO和Permission類中是ControllerName、ActionName和ControllerNo、ActionNO是對應的。

步驟三、給Controllers打上DescriptionAttribute標簽

使用步驟二創建的DescriptionAttribute標簽給Controller標上,以便存儲Permission的時候獲取信息。如下面的代碼:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Mvc;
 6 
 7 namespace SampleMVCWebsite.Controllers
 8 {
 9 [Description(No = 1, Name = "用戶")]
10     public class UserController : Controller
11     {
12         [RoleAuthorize]
13         [Description(No = 1, Name = "用戶首頁")]
14         public ActionResult Index()
15         {
16             return View();
17         }
18         [RoleAuthorize]
19         [Description(No = 1, Name = "用戶管理員")]
20         public ActionResult Manage()
21         {
22             return View();
23         }
24         [RoleAuthorize]
25         [Description(No = 1, Name = "用戶詳情")]
26         public ActionResult Detail()
27         {
28             return View();
29         }
30     }
31 }

 

 

步驟四、生成權限控制列表

步驟一種有一個role.Permissions,這個Permissions就是當前用戶所擁有的權限集合,在實際的項目開發中是把它存儲在數據庫關系表中的,我們可以將Permissions類如下面的代碼這樣定義

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5  
 6 namespace SampleMVCWebsite
 7 {
 8     public class Permission
 9     {
10         /// <summary>
11         /// Permission Id
12         /// </summary>
13         public virtual int Id
14         {
15             set;
16             get;
17         }
18         /// <summary>
19         /// Permission Action No
20         /// </summary>
21         public virtual int ActionNo
22         {
23             set;
24             get;
25         }
26  
27         /// <summary>
28         /// Controller No
29         /// </summary>
30         public virtual int ControllerNo
31         {
32             set;
33             get;
34         }
35 
36         /// <summary>
37         /// Controller Name
38         /// </summary>
39         public virtual string ControllerName
40         {
41             set;
42             get;
43         }
44 
45         /// <summary>
46         /// Permission Action Name
47         /// </summary>
48         public virtual string ActionName
49         {
50             set;
51             get;
52         }
53  
54         /// <summary>
55         /// Controller
56         /// </summary>
57         public virtual string Controller
58         {
59             set;
60             get;
61         }
62 
63         /// <summary>
64         /// Action
65         /// </summary>
66         public virtual string Action
67         {
68             set;
69             get;
70         }
71     }
72 }

 

屬性Controller和Action記錄的是權限,ControllerName和ActionName用於顯示UI,ControllerNo和ActionNo用於顯示順序控制。其余根據上面的代碼注釋應該很好理解,這里就不一一陳述了。

因此你需要將Action輸入數據庫中來實現RoleApi。手動輸入如果方法少還好,但是多了就比較麻煩,這樣我們可以使用.NET的反射機制來進行權限的創建。先看下面的代碼:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Mvc;
 6 using SampleMVCWebsite.Controllers;
 7 
 8 namespace SampleMVCWebsite
 9 {
10     public class InstallController
11     {
12         public class InstallController : Controller
13         {
14             public ActionResult Index()
15             {
16                 return View();
17             }
18 
19             [HttpPost]
20             public ActionResult Index()
21             {
22                 try
23                 {
24                     var roleService = new RoleApi();
25                     #region init permission
26                     CreatePermission(new UserController());
27                     #endregion
28 
29                     var allDefinedPermissions = roleService.GetDefinedPermissions();
30 
31                     #region 管理員角色初始化
32                     var adminPermissions = new List<RolePermissionInfo>();
33                     foreach (var d in allDefinedPermissions)
34                     {
35                         adminPermissions.Add(new RolePermissionInfo {Permission = d, });
36                     }
37                     int adminRoleId = roleService.AddRole(new RoleInfo
38                     {
39                         Name = "管理員",
40                         Description = "",
41                         Permissions = adminPermissions,
42                         AddDate = DateTime.Now,
43                     });
44                     #endregion
45                     return RedirectToAction("Admin", "Index");
46                 }
47                 catch (Exception ex)
48                 {
49                     ModelState.AddModelError("", ex.Message);
50                     return View();
51                 }
52             }
53             private void CreatePermission(Controller customController)
54             {
55                 var roleApi = new RoleApi();
56 
57                 var controllerName = "";
58                 var controller = ""; var controllerNo = 0;
59                 var actionName = ""; var action = ""; var actionNo = 0;
60                 var controllerDesc = new KeyValuePair<string, int>();
61 
62                 var controllerType = customController.GetType();
63 
64                 //remove controller posfix
65                 controller = controllerType.Name.Replace("Controller", "");
66                 controllerDesc = Getdesc(controllerType);
67                 if (!string.IsNullOrEmpty(controllerDesc.Key))
68                 {
69                     controllerName = controllerDesc.Key;
70                     controllerNo = controllerDesc.Value;
71                     foreach (var m in controllerType.GetMethods())
72                     {
73                         var mDesc = GetPropertyDesc(m);
74                         if (string.IsNullOrEmpty(mDesc.Key)) continue;
75                         action = m.Name;
76                         actionName = mDesc.Key;
77                         actionNo = mDesc.Value;
78                         roleApi.CreatePermissions(actionNo, controllerNo, actionName, controllerName, controller, action);
79                     }
80                 }
81             }
82             private KeyValuePair<string, int> Getdesc(Type type)
83             {
84                 var descriptionAttribute = (DescriptionAttribute)(type.GetCustomAttributes(false).FirstOrDefault(x => x is DescriptionAttribute));
85                 if (descriptionAttribute == null) return new KeyValuePair<string, int>();
86                 return new KeyValuePair<string, int>(descriptionAttribute.Name, descriptionAttribute.No);
87             }
88             private KeyValuePair<string, int> GetPropertyDesc(System.Reflection.MethodInfo type)
89             {
90                 var descriptionAttribute = (DescriptionAttribute)(type.GetCustomAttributes(false).FirstOrDefault(x => x is DescriptionAttribute));
91                 if (descriptionAttribute == null) return new KeyValuePair<string, int>();
92                 return new KeyValuePair<string, int>(descriptionAttribute.Name, descriptionAttribute.No);
93             }
94         }
95     }
96 }
97 上面的代碼首先通過Getdesc來獲取Controller的描述,GetPropertyDesc

 

方法獲取方法的描述,這里的方法就是一個獨立的權限,然后通過roleApi的CreatePermissions方法將權限的數據寫入到數據庫中,將數據寫入數據庫的代碼就需要根據自己的數據庫讀寫方法去實現了,強烈建議使用Linq對數據庫進行讀寫。然后再通過roleApi獲取到所有的權限並且將所有的權限綁定到Admin角色,保存對應關系。這樣我們就完成了權限控制列表生成並且初始化了管理員用戶。

通過上面的示例就可以完成ASP.NET MVC 基於角色的權限控制系統,上面的代碼中的roleApi需要自己寫代碼實現對數據庫的操作,數據模型就是權限、角色、用戶的數據表以及權限月角色以及角色與用戶的關系表。


免責聲明!

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



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