ASP.NET MVC 基于角色的权限控制系统的示例教程

上一次在 .NET MVC 用户权限管理示例教程中讲解了ASP.NET MVC 通过AuthorizeAttribute类的OnAuthorization方法讲解了粗粒度控制权限的方法,接下来讲解基于角色的权限控制方法。

基于角色的权限控制方法概述

基于角色的权限控制系统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需要自己写代码实现对数据库的操作,数据模型就是权限、角色、用户的数据表以及权限月角色以及角色与用户的关系表。

时间: 2024-10-26 23:50:36

ASP.NET MVC 基于角色的权限控制系统的示例教程的相关文章

ASP.net MVC 基于角色的权限控制系统的实现

一.引言 我们都知道ASP.net mvc权限控制都是实现AuthorizeAttribute类的OnAuthorization方法. 下面是最常见的实现方式: public class CustomAuthorizeAttribute : AuthorizeAttribute { public override void OnAuthorization(AuthorizationContext filterContext) { if (!filterContext.RequestContext

基于角色的权限访问控制初步

基于角色的权限访问控制(Role-Based Access Control) 角色访问控制(RBAC)引入了role的概念,目的是为了隔离user(即动作主体,subject)与privilege(权限,表示对resource的一个操作,即operation+resource).role作为一个用户(user)与权限(privilege)的代理层,解耦了权限和用户的关系,所有的授权应该给予role而不是直接给user或 group.privilege是权限颗粒,由operation和resour

基于角色的权限管理系统

我们开发业务系统的时候,基本上都会涉及到权限管理模块,要求不同的人看到不同的菜单,操作不同的按钮,看到不同的数据.很多初学者面对这样的需求不知道如何下手,特别是稍微复杂点的权限,更是找不到方向,为此我们夜鹰教程网特别推出了这套基于角色的权限管理视频教程,通过给用户分配角色,给角色分配权限,来实现权限管理.这样一来,可以实现不同的人管理不同的菜单,操作不同的按钮,看到不同的数据.可以划分权限组,每个组的成员拥有相同的权限.也可以把同一个人分配到不同的权限组,具有多个权限组的权限,实现权限的组合.

从零开始——基于角色的权限管理01(补充)

此博文较为详细的介绍从零开始--基于角色的权限管理01文中的两个部分的流程(解释代码). 1) index.jsp中提交跳转action action的login,获取jsp页面传过来的用户名密码和验证码,进行验证 首先到userDao中,执行login方法,判断是否存在这组用户名和密码 接着到roleDao中,执行getRoleNameById以获取角色名 最后,进入main.jsp中 2)在main.jsp中,有一个树的显示,再次进入authServlet中执行menuAction   先后

基于角色的权限控制

首先要明白的有一个表就是需要记录整个项目中控制器和方法,这样在权限检测的时候就可以检测数据库对应的角色有没有这个控制器或者方法的权限, 但是需要明白的是在开发的过程中当然需要把这种权限给取消,这样在开发过程是需要增加一个控制器或者方法就不需要验证权限,然后开发好了之后就需要 在权限表中增加该控制器和方法. 一般基于角色的权限控制,需要用到下面的几张表 1.用户表2,权限表,3.角色表,4权限角色关系表5用户角色关系表 这种方式是用户通过,用户角色关系表查询出自己的角色,然后通过权限角色关系表查出

使用Lync 2013 基于角色的权限控制:RBAC 给用户分配指定的操作权限

使用场景: 在大型的Lync统一沟通系统的日常运维中,我们需要为不同角色的管理员分配不同的Lync管理权限,在Lync Server 2013上面就使用了基于角色的权限控制:RBAC ,它里面分了多种权限角色,包括 CsAdministrator,CsUserAdministrator,CsVoiceAdministrator,CsServerAdministrator,CsViewOnlyAdministrator,CsHelpDesk等等,不同的角色有不同的Lync管理权限, 例如,当我们只

ASP.NET MVC基于标注特性的Model验证:将ValidationAttribute应用到参数上

原文:ASP.NET MVC基于标注特性的Model验证:将ValidationAttribute应用到参数上 ASP.NET MVC默认采用基于标准特性的Model验证机制,但是只有应用在Model类型及其属性上的ValidationAttribute才有效.如果我们能够将ValidationAttribute特性直接应用到参数上,我们不但可以实现简单类型(比如int.double等)数据的Model验证,还能够实现“一个Model类型,多种验证规则”,本篇文章将为你提供相关的解决方案(源代码

ASP.NET MVC基于标注特性的Model验证:一个Model,多种验证规则

原文:ASP.NET MVC基于标注特性的Model验证:一个Model,多种验证规则 对于Model验证,理想的设计应该是场景驱动的,而不是Model(类型)驱动的,也就是对于同一个Model对象,在不同的使用场景中可能具有不同的验证规则.举个简单的例子,对于一个表示应聘者的数据对象来说,针对应聘的岗位不同,肯定对应聘者的年龄.性别.专业技能等方面有不同的要求.但是ASP.NET MVC的Model验证确是Model驱动的,因为验证规则以验证特性的形式应用到Model类型及其属性上.这样的验证

基于角色的权限设计(一)

在任何系统中,权限设计是最基础的东西,本文给出一个基于角色的权限设计的循序渐进的设计方案. 在权限系统中,功能(权限)是最小的单位,比如起草新闻.编辑新闻.审核新闻.删除新闻等,而角色是一类功能的集合,比如新闻编辑 这个角色,他可能有起草新闻.编辑新闻等功能集合,而责任编辑他可能就有更多的权限,比如除了新闻编辑的功能,还有审核新闻.删除新闻等功能,给张三赋予 新闻编辑的角色(其实我更愿意说把张三加入到新闻编辑这个角色中去),张三就可以起草新闻.编辑新闻了,给李四赋予责任编辑的角色,李四就可以起草