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

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

.NET MVC 用戶角色權限控制

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

基於角色的權限控制系統RBAC(Role Based Access Control)是目前最流行,也是最通用的權限控制系統。所謂基於角色的權限控制,就是將各個操做權限分組,每個組就是一個角色,舉個例子:管理員擁有全部的權限,編輯就只擁有寫文章和發佈文章的權限,這裏的「管理員」和「編輯」就是一個角色——一系列操做權限的集合。咱們只須要將某個角色賦予某個用戶那麼這個用戶就擁有這個角色下的權限集合。web

 

如今咱們要作的就是經過把Controller下的每個Action能夠看做是一個權限,而後能夠經過方法將每個權限進行自定義的分組,從而建立一個角色,而後將角色與用戶對應起來。數據庫

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

步驟1、新建一個RoleAuthorizeAttribute類

這個類能夠拿到ControllerName和ActionName,這樣能夠根據ControllerName和ActionName判斷是什麼樣的操做,以下面的代碼mvc

 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官網。ide

PS:這裏用Ticket的Version存儲RoleId。你也能夠用其餘方式。關於Ticket的知識能夠參考微軟MSDN官方文檔,這裏再也不敖述。spa

步驟2、建立DescriptionAttribute類

這個類是繼承Attribute,爲的是給Action方法打上描述標籤,以下面的代碼code

 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是對應的。orm

步驟3、給Controllers打上DescriptionAttribute標籤

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

 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 }

 

 

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

步驟一種有一個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須要本身寫代碼實現對數據庫的操做,數據模型就是權限、角色、用戶的數據表以及權限月角色以及角色與用戶的關係表。

相關文章
相關標籤/搜索