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

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

基于角色的权限控制系统RBAC(Role Based Access Control)是目前最流行,也是最通用的权限控制系统。所谓基于角色的权限控制,就是将各个操作权限分组,每一个组就是一个角色,举个例子:管理员拥有所有的权限,编辑就只拥有写文章和发布文章的权限,这里的“管理员”和“编辑”就是一个角色——一系列操作权限的集合。我们只需要将某个角色赋予某个用户那么这个用户就拥有这个角色下的权限集合。

现在我们要做的就是通过把Controller下的每一个Action可以看作是一个权限,然后可以通过方法将每一个权限进行自定义的分组,从而创建一个角色,然后将角色与用户对应起来。

基于角色的权限控制方法步骤

步骤一、新建一个RoleAuthorizeAttribute类

这个类可以拿到ControllerName和ActionName,这样可以根据ControllerName和ActionName判断是什么样的操作,如下面的代码

 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官网。

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

步骤二、创建DescriptionAttribute类

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

 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是对应的。

步骤三、给Controllers打上DescriptionAttribute标签

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

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

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

步骤一种有一个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 = ;
var actionName = ""; var action = ""; var actionNo = ;
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需要自己写代码实现对数据库的操作,数据模型就是权限、角色、用户的数据表以及权限月角色以及角色与用户的关系表。

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

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

    一.引言 我们都知道ASP.net mvc权限控制都是实现AuthorizeAttribute类的OnAuthorization方法. 下面是最常见的实现方式: public class Custom ...

  2. 基于角色的权限控制系统(role-based access control)

    role-based access control(rbac),指对于不同角色的用户,拥有不同的权限 .用户对应一个角色,一个角色拥有若干权限,形成用户-角色-权限的关系,如下图所示.当一个用户进行访 ...

  3. ASP.NET MVC 基于页面的权限管理

    菜单表 namespace AspNetMvcAuthDemo1.Models { public class PermissionItem { public int ID { set; get; } ...

  4. MVC基于角色权限控制--数据库设计

    在网站后台设计过程中都会遇上权限控制这一问题 当前较为流行的解决方案是基于角色的权限管理 基本思路如下 分别建立 用户信息表.角色信息表.权限信息表 让用户和角色关联,角色和权限关联,当用户访问时,通 ...

  5. Asp.net core IdentityServer4与传统基于角色的权限系统的集成

    写在前面 因为最近在忙别的,好久没水文了 今天来水一篇: 在学习或者做权限系统技术选型的过程中,经常有朋友有这样的疑问 : "IdentityServer4的能不能做到与传统基于角色的权限系 ...

  6. FineAdmin.Mvc 使用ok-admin+ASP.NET MVC搭建的通用权限后台管理系统

    FineAdmin.Mvc 介绍 使用ok-admin+ASP.NET MVC搭建的通用权限后台管理系统RightControl后台layui模板不太好看,换成ok-admin v2.0重写一遍.项目 ...

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

    原文:ASP.NET MVC基于标注特性的Model验证:将ValidationAttribute应用到参数上 ASP.NET MVC默认采用基于标准特性的Model验证机制,但是只有应用在Model ...

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

    原文:ASP.NET MVC基于标注特性的Model验证:一个Model,多种验证规则 对于Model验证,理想的设计应该是场景驱动的,而不是Model(类型)驱动的,也就是对于同一个Model对象, ...

  9. C 实现基于角色的权限系统

    本文demo下载地址:http://www.wisdomdd.cn/Wisdom/resource/articleDetail.htm?resourceId=1068 实例使用C# 实现基于角色的权限 ...

随机推荐

  1. Linux下的字符集问题

    怎么设置Linux系统中文语言,这是很多小伙伴在开始使用Linux的时候,都会遇到一个问题,就是终端输入命令回显的时候中文显示乱码.出现这个情况一般是由于没有安装中文语言包,或者设置的默认语言有问题导 ...

  2. android平台的技术架构

    Android平台采用了软件堆层(Software Stack)的架构,主要分为四个部分: 1.应用软件 Android 连同一个核心应用程序包一起发布,该应用程序包包括E-mail客户端.SMS短消 ...

  3. BestCoder Valentine's Day Round

    昨晚在开赛前5分钟注册的,然后比赛刚开始就掉线我就不想说了(蹭网的下场……),只好用手机来看题和提交,代码用电脑打好再拉进手机的(是在傻傻地用手机打了一半后才想到的办法). 1001,也就是 hdu ...

  4. LINUX多线程(一)(创建和退出)

    1. Linux多线程概述 1.1. 概述 进程是系统中程序执行和资源分配的基本单位.每个进程有自己的数据段.代码段和堆栈段.这就造成进程在进行切换等操作时都需要有比较负责的上下文切换等动作.为了进一 ...

  5. jquery中DOM

    节点包裹 wrap() (1)$().wrap(html) 将选择的节点用指定的元素包装 $('p').wrap('<div></div>'); (2)多层包裹 $('p'). ...

  6. phalcon:model 事件与事件管理器

    事件与事件管理器(Events and Events Manager)¶ Models allow you to implement events that will be thrown when p ...

  7. VB6 GDI+ 入门教程[6] 图片

    http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[6] 图片 2009 年 6 月 19 日 15条评论 ...

  8. C/C++中的abort、atexit、exit和_Exit

    这几个函数都在头文件#include <stdlib.h>中声明.exit._Exit与abort函数使程序终止,控制并不返回到这些函数的调用者. exit()函数 void exit(i ...

  9. HTML5中的文本级语义

    <p>这篇文章的发布时间是<time datetime="2016-02-26T16:30+08:00" pubdate>今天</time>&l ...

  10. C# Socket编程(1)基本的术语和概念

    计算机程序能够相互联网,相互通讯,这使一切都成为可能,这也是当今互联网存在的基础.那么程序是如何通过网络相互通信的呢?这就是我记录这系列的笔记的原因.C#语言从一开始就是为了互联网而设计的,它为实现程 ...