MVC4 Simplemembership实现用户权限管理-权限控制
上篇文章我们对默认的Membership数据库进行了扩展,接下来实现对具体的Controller和Action进行控制。
我们使用mvc的AuthorizeAttribute来实现对Controller and Action权限控制。类似下面效果
- using System;
 - using System.Collections.Generic;
 - using System.Linq;
 - using System.Web;
 - using System.Web.Mvc;
 - using TYStudio;
 - namespace TYStudioSimplemembership.Controllers
 - {
 - /// <summary>
 - /// 这是一个产品权限的测试Controller
 - /// </summary>
 - ///
 - [Authorize]
 - [InitializeSimpleMembership]
 - public class ProductController : Controller
 - {
 - [TYStudioAuthorize("查询产品")]
 - public ActionResult Index()
 - {
 - return View();
 - }
 - [TYStudioAuthorize("添加产品")]
 - public ActionResult Create()
 - {
 - return View();
 - }
 - [TYStudioAuthorize("修改产品")]
 - public ActionResult Edit()
 - {
 - return View();
 - }
 - [TYStudioAuthorize("删除产品")]
 - public ActionResult Delete()
 - {
 - return View();
 - }
 - }
 - }
 
首先介绍一下上面以前的Permission表和PermissionsInRoles表的使用,Permission表要存储各个Action的名字(例如一个一个controller中的曾删改查各个Action),或者自己起一个别名,别名主要用于给配置权限的管理人员使用。PermissionsInRoles表就是存储权限和角色关系的了。例如管理员角色具有所有增删改查权限,一般用户角色只有查看权限,我们可以在这里配置。
接下来我们建立一个自己的TYStudioAuthorizeAttribute继承AuthorizeAttribute,并重写AuthorizeCore和HandleUnauthorizedRequest方法。
代码如下:(接下来会解释各个函数的用途)
- [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
 - public class TYStudioAuthorizeAttribute : AuthorizeAttribute
 - {
 - private readonly bool _authorize;
 - private bool _isPermissionFail = false;
 - public TYStudioAuthorizeAttribute()
 - {
 - if (HttpContext.Current.User.Identity.Name != "")
 - {
 - _authorize = true;
 - }
 - else
 - {
 - _authorize = false;
 - }
 - }
 - public TYStudioAuthorizeAttribute(string permission)
 - {
 - if (HttpContext.Current.User.Identity.Name != "")
 - {
 - _authorize = PermissionManager.CheckUserHasPermision(HttpContext.Current.User.Identity.Name, permission);
 - if (_authorize == false)
 - {
 - _isPermissionFail = true;
 - }
 - }
 - else
 - {
 - _authorize = false;
 - }
 - //_authorize = true;
 - }
 - protected override bool AuthorizeCore(HttpContextBase httpContext)
 - {
 - return _authorize;
 - }
 - protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
 - {
 - if (_isPermissionFail)
 - {
 - filterContext.HttpContext.Response.Redirect("/Admin/PermissionError");
 - }
 - else
 - {
 - base.HandleUnauthorizedRequest(filterContext);
 - }
 - }
 - }
 
首先看一下构造函数TYStudioAuthorizeAttribute(string permission),接受一个permission字符串,这个就是Permission表中的数据,对应着每个Action。
在这个构造参数里判断当前用户是否具有permission这个权限。PermissionManager.CheckUserHasPermision(HttpContext.Current.User.Identity.Name, permission),如果有赋值true给_authorize,表示当前用户有权限访问这个Action。如果没有赋值false给_authorize。
PermissionManager这个类主要是取得当前登录用户的角色,然后通过PermissionsInRoles表中的数据判断是否有这个权限,下面是PermissionManager的code,第一次取出所有权限放在缓存里面。
- using System;
 - using System.Xml;
 - using System.IO;
 - using System.Web;
 - using System.Web.Caching;
 - using System.Collections.Generic;
 - using System.Configuration;
 - using System.Web.Security;
 - using System.Linq;
 - using WebMatrix.WebData;
 - namespace TYStudio
 - {
 - public class PermissionManager
 - {
 - public static bool CheckUserHasPermision(string userName, string permissionName)
 - {
 - List<Role> roleList = new List<Role>();
 - List<PermissionsInRoles> permissionsInRolesList = new List<PermissionsInRoles>();
 - if (HttpRuntime.Cache.Get("Roles") == null)
 - {
 - using (TYStudioMembershipContext db = new TYStudioMembershipContext())
 - {
 - roleList = db.Roles.AsEnumerable<Role>().ToList<Role>();
 - HttpRuntime.Cache.Insert("Roles", roleList);
 - }
 - }
 - if (HttpRuntime.Cache.Get("PermissionsInRoles") == null)
 - {
 - using (TYStudioMembershipContext db = new TYStudioMembershipContext())
 - {
 - permissionsInRolesList = db.PermissionsInRoles
 - .Include("Permission").Include("Role")
 - .AsEnumerable<PermissionsInRoles>().ToList<PermissionsInRoles>();
 - HttpRuntime.Cache.Insert("PermissionsInRoles", permissionsInRolesList);
 - }
 - }
 - string[] currentRoles = new string[] { };
 - if (HttpRuntime.Cache.Get("CurrentRoles") == null)
 - {
 - currentRoles = Roles.GetRolesForUser(userName);
 - HttpRuntime.Cache.Insert("CurrentRoles", currentRoles);
 - }
 - currentRoles = HttpRuntime.Cache.Get("CurrentRoles") as string[];
 - roleList = HttpRuntime.Cache.Get("Roles") as List<Role>;
 - permissionsInRolesList = HttpRuntime.Cache.Get("PermissionsInRoles") as List<PermissionsInRoles>;
 - foreach (var roleName in currentRoles)
 - {
 - List<Permission> permissionList = permissionsInRolesList.Where(e => e.Role.RoleName == roleName)
 - .Select(e => e.Permission).ToList<Permission>();
 - foreach (var permission in permissionList)
 - {
 - if (permission.PermissionName == permissionName)
 - {
 - return true;
 - }
 - }
 - }
 - return false;
 - }
 - }
 - }
 
在AuthorizeCore中我们直接返回_authorize。(当然验证权限的代码完全可以放到这个函数里面)
当返回值为true的时候,系统会允许当前用户处理Action的请求,当返回false的时候,就需要重写的另外一个方法HandleUnauthorizedRequest(AuthorizationContext filterContext),我们可以在这里控制用户没有权限的时候,新建一个错误跳转的页面并加上相应的提示。
文章开始代码中的,查看产品,查看产品详细内容,添加产品,修改产品,删除产品就是Permissions表中存的具体权限数据。
本篇文章只是一个提供意思使用Simplemembership的思路,希望能给你一些灵感,如果有什么问题或者想要源代码,可以留下评论,我会及时回复的。
原创文章,转载请注明出处,谢谢。






这样设计是否需要手动把所有Action(或别名)都添加到数据库中呢?能否通过反射机制把所有的Action名称(或别名)读取出来提供选择呢?
你的这个建议很好,但是即使把所有的Action名称得到,一样需要进行别名配置。代码的Action是用户是看不懂的。
其实就是,能否把别名也反射出去呢,哈哈
可以发一份代码给我吗?
给我一下你的邮箱吧,我发给你。
165619258@qq.com,谢谢。
已发送给你一个全新的版本思路是一样的,发送给你的是一个后台权限管理系统可以直接使用。
非常感谢。先研究,有问题再留言。或者给您发邮件。
我在调试你的代码的时候,发现你扩展的model并没有新建数据表,是需要手动创建吗?
你需要修改一下,TYStudioUsersConnectionString,改成你本地数据库的用户名密码。
那个我改了,也生成表了,不过是MVC4的表,至于Permission那些扩展的表并没有建立。
416362007你加我qq
求源码!jarrett_zhou@sina.cn
看这篇文章有下载,http://www.tystudio.net/2013/03/20/mvc4-simplemembership-permission-system/
呵呵,我的是VS2010打不开项目,我已经下载,我有个问题想请教你,就是MVC4中怎么操作2个实体多对多关系 的那张映射表,也是说用户 和权限的关系角色表EF是怎么操作的!我是新手还望赐教!
恩,项目是VS2012的工程开发的,2010我记得是mvc3吧,建好主外键关系之后可以直接用点的方式点出来关联的表,你说有点笼统,能具体一些么
我装了插件也能做mvc4,比如说一张用户表,一张权限表,我现在呀给用户添加权限,怎么实现!
一般的是用户和角色关联,角色和权限关联。 如果你不用角色,直接用户和权限关联,建一个UserPermission表,里面有User_ID,Permission_ID,两个分别建好外键,添加关系的时候,直接new 一个UserPermission给两个id赋值后保存就可以了,前提是还得有一个Permission表。
扩展的AuthorizeAttribute在程序第一次运行时被调用执行,当重新赋予新的权限时,该方法就不执行了。使用一个赋予了新权限的用户登录后,新权限并没有起作用,即没有在执行具体action时调用AuthorizeAttribute。求解。
现在这个程序在前台直接添加新权限是不起作用的,需要在后台代码中添加相应的权限。这里有点说不清楚,你可以再联系页面找到我的qq加我,咱们qq直接交流。
好文,
需要源码,网上的源码无法下载
我的邮箱284171004@qq.com
bucuo
可以控制到页面上的按钮权限不
目前这个不能控制到按钮
还有你能发一份源码给我不? 305576089@qq.com 在弄用户权限设计到页面按钮的时候不知道怎么处理。
这个控制不到页面的按钮