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 在弄用户权限设计到页面按钮的时候不知道怎么处理。
这个控制不到页面的按钮