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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.Mvc;
using System.Web.Routing;

namespace SampleMVCWebsite
{
    public class RoleAuthorizeAttribute : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            var isAuth = false;
            if (!filterContext.RequestContext.HttpContext.Request.IsAuthenticated)
            {
                isAuth = false;
            }
            else
            {
                if (filterContext.RequestContext.HttpContext.User.Identity != null)
                {
                    var roleApi = new RoleApi();
                    var actionDescriptor = filterContext.ActionDescriptor;
                    var controllerDescriptor = actionDescriptor.ControllerDescriptor;
                    var controller = controllerDescriptor.ControllerName;
                    var action = actionDescriptor.ActionName;
                    var ticket = (filterContext.RequestContext.HttpContext.User.Identity as FormsIdentity).Ticket;
                    var role = roleApi.GetById(ticket.Version);
                    if (role != null)
                    {
                        isAuth = role.Permissions.Any(x => x.Permission.Controller.ToLower() == controller.ToLower() && x.Permission.Action.ToLower() == action.ToLower());
                    }
                }
            }
            if (!isAuth)
            {
                filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "account", action = "login", returnUrl = filterContext.HttpContext.Request.Url, returnMessage = "您无权查看." }));
                return;
            }
            else
            {
                base.OnAuthorization(filterContext);
            }
        }
    }
}

 

其中RoleApi是角色对象管理的API,这里须要本身设置角色管理。上面的代码中经过FilterContext的ActionDescriptor对象的ControllerDescriptor就能够获取到ControllerName和ActionName。获取到当前用户的角色后,经过查看用户的权限中是否包含了当前访问的Controller中的方法,就能实现权限验证。这里主要使用了ActionDescriptor和ControllerDescriptor,关于这两个类的介绍能够参考MSDN官网。ide

PS:这里用Ticket的Version存储RoleId。你也能够用其余方式。关于Ticket的知识能够参考微软MSDN官方文档,这里再也不敖述。spa

步骤2、建立DescriptionAttribute类

这个类是继承Attribute,为的是给Action方法打上描述标签,以下面的代码code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace SampleMVCWebsite
{
    /// <summary>
    /// Description Attribute
    /// </summary>
    public class DescriptionAttribute:Attribute
    {
        public string Name
        {
            set;
            get;
        }
        public int No
        {
            set;
            get;
        }
    }
}

 

Name和NO和Permission类中是ControllerName、ActionName和ControllerNo、ActionNO是对应的。orm

步骤3、给Controllers打上DescriptionAttribute标签

使用步骤二建立的DescriptionAttribute标签给Controller标上,以便存储Permission的时候获取信息。以下面的代码:htm

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace SampleMVCWebsite.Controllers
{
[Description(No = 1, Name = "用户")]
    public class UserController : Controller
    {
        [RoleAuthorize]
        [Description(No = 1, Name = "用户首页")]
        public ActionResult Index()
        {
            return View();
        }
        [RoleAuthorize]
        [Description(No = 1, Name = "用户管理员")]
        public ActionResult Manage()
        {
            return View();
        }
        [RoleAuthorize]
        [Description(No = 1, Name = "用户详情")]
        public ActionResult Detail()
        {
            return View();
        }
    }
}

 

步骤4、生成权限控制列表

步骤一种有一个role.Permissions,这个Permissions就是当前用户所拥有的权限集合,在实际的项目开发中是把它存储在数据库关系表中的,咱们能够将Permissions类以下面的代码这样定义对象

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace SampleMVCWebsite
{
    public class Permission
    {
        /// <summary>
        /// Permission Id
        /// </summary>
        public virtual int Id
        {
            set;
            get;
        }
        /// <summary>
        /// Permission Action No
        /// </summary>
        public virtual int ActionNo
        {
            set;
            get;
        }
 
        /// <summary>
        /// Controller No
        /// </summary>
        public virtual int ControllerNo
        {
            set;
            get;
        }

        /// <summary>
        /// Controller Name
        /// </summary>
        public virtual string ControllerName
        {
            set;
            get;
        }

        /// <summary>
        /// Permission Action Name
        /// </summary>
        public virtual string ActionName
        {
            set;
            get;
        }
 
        /// <summary>
        /// Controller
        /// </summary>
        public virtual string Controller
        {
            set;
            get;
        }

        /// <summary>
        /// Action
        /// </summary>
        public virtual string Action
        {
            set;
            get;
        }
    }
}

属性Controller和Action记录的是权限,ControllerName和ActionName用于显示UI,ControllerNo和ActionNo用于显示顺序控制。其他根据上面的代码注释应该很好理解,这里就不一一陈述了。

所以你须要将Action输入数据库中来实现RoleApi。手动输入若是方法少还好,可是多了就比较麻烦,这样咱们能够使用.NET的反射机制来进行权限的建立。先看下面的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SampleMVCWebsite.Controllers;

namespace SampleMVCWebsite
{
    public class InstallController
    {
        public class InstallController : Controller
        {
            public ActionResult Index()
            {
                return View();
            }

            [HttpPost]
            public ActionResult Index()
            {
                try
                {
                    var roleService = new RoleApi();
                    #region init permission
                    CreatePermission(new UserController());
                    #endregion

                    var allDefinedPermissions = roleService.GetDefinedPermissions();

                    #region 管理员角色初始化
                    var adminPermissions = new List<RolePermissionInfo>();
                    foreach (var d in allDefinedPermissions)
                    {
                        adminPermissions.Add(new RolePermissionInfo {Permission = d, });
                    }
                    int adminRoleId = roleService.AddRole(new RoleInfo
                    {
                        Name = "管理员",
                        Description = "",
                        Permissions = adminPermissions,
                        AddDate = DateTime.Now,
                    });
                    #endregion
                    return RedirectToAction("Admin", "Index");
                }
                catch (Exception ex)
                {
                    ModelState.AddModelError("", ex.Message);
                    return View();
                }
            }
            private void CreatePermission(Controller customController)
            {
                var roleApi = new RoleApi();

                var controllerName = "";
                var controller = ""; var controllerNo = 0;
                var actionName = ""; var action = ""; var actionNo = 0;
                var controllerDesc = new KeyValuePair<string, int>();

                var controllerType = customController.GetType();

                //remove controller posfix
                controller = controllerType.Name.Replace("Controller", "");
                controllerDesc = Getdesc(controllerType);
                if (!string.IsNullOrEmpty(controllerDesc.Key))
                {
                    controllerName = controllerDesc.Key;
                    controllerNo = controllerDesc.Value;
                    foreach (var m in controllerType.GetMethods())
                    {
                        var mDesc = GetPropertyDesc(m);
                        if (string.IsNullOrEmpty(mDesc.Key)) continue;
                        action = m.Name;
                        actionName = mDesc.Key;
                        actionNo = mDesc.Value;
                        roleApi.CreatePermissions(actionNo, controllerNo, actionName, controllerName, controller, action);
                    }
                }
            }
            private KeyValuePair<string, int> Getdesc(Type type)
            {
                var descriptionAttribute = (DescriptionAttribute)(type.GetCustomAttributes(false).FirstOrDefault(x => x is DescriptionAttribute));
                if (descriptionAttribute == null) return new KeyValuePair<string, int>();
                return new KeyValuePair<string, int>(descriptionAttribute.Name, descriptionAttribute.No);
            }
            private KeyValuePair<string, int> GetPropertyDesc(System.Reflection.MethodInfo type)
            {
                var descriptionAttribute = (DescriptionAttribute)(type.GetCustomAttributes(false).FirstOrDefault(x => x is DescriptionAttribute));
                if (descriptionAttribute == null) return new KeyValuePair<string, int>();
                return new KeyValuePair<string, int>(descriptionAttribute.Name, descriptionAttribute.No);
            }
        }
    }
}

上面的代码首先经过Getdesc来获取Controller的描述,GetPropertyDesc方法获取方法的描述,这里的方法就是一个独立的权限,而后经过roleApi的CreatePermissions方法将权限的数据写入到数据库中,将数据写入数据库的代码就须要根据本身的数据库读写方法去实现了,强烈建议使用Linq对数据库进行读写。而后再经过roleApi获取到全部的权限而且将全部的权限绑定到Admin角色,保存对应关系。这样咱们就完成了权限控制列表生成而且初始化了管理员用户。

经过上面的示例就能够完成ASP.NET MVC 基于角色的权限控制系统,上面的代码中的roleApi须要本身写代码实现对数据库的操做,数据模型就是权限、角色、用户的数据表以及权限月角色以及角色与用户的关系表。

相关文章
相关标签/搜索