MVC中权限的知识点及具体实现代码

一:知识点部分

权限是做网页经常要涉及到的一个知识点,在使用MVC做权限设计时需要先了解以下知识:

MVC中Url的执行是按照Controller->Action->View页面,但是我们经常需要在函数执行所指定的Action之前或者action方法之后处理一些逻辑,为了处理这些逻辑,ASP.NET MVC允许你创建action过滤器Filter,我们都知道在Action上使用的每一个 [Attribute]大都是自定义的Filter。

mvc提供四种类型的Filter接口:IActionFilter,IAuthorizationFilter,IExceptionFilter,IResultFilter, 这四种Filter足以满足我们所要实现的功能,它还提供了几个现

成的可以使用的Filter:OutputCacheAttribute、 HandleErrorAttribute、AuthorizeAttribute。(AuthorizeAttribute 和 HandleErrorAttribute继承自FilterAttribute 类)

其中:

IActionFilter提供的两种方法: OnActionExecuting 在调用操作方法前调用。OnActionExecuted 在调用操作方法后调用。

IResultFilter提供的两种方法:OnResultExecuting 在执行由操作方法返回的操作结果前调用。OnResultExecuted 在执行由操作方法返回的操作结果后调用。

IAuthorizationFilter是一个用于身份验证的Filter。只提供了一个void OnAuthorization(AuthorizationContext filterContext)方法。

IExceptionFilter会在出现异常的时候调用,也是只提供一个void OnException(ExceptionContext filterContext)的方法;

而4个接口的方法执行顺序如下:IAuthorizationFilter -> IActionFilter - >IResultFilter ->IExceptionFilter

【 ActionExecutedContext类包含一个 Canceled的属性,允许你取消当前的 Action】

现在我们来看一下用得最多的一个类ActionFilterAttribute:

他的继承层次结构为

System.Object
  System.Attribute
    System.Web.Mvc.FilterAttribute
      System.Web.Mvc.ActionFilterAttribute
        System.Web.Mvc.AsyncTimeoutAttribute
        System.Web.Mvc.OutputCacheAttribute

public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IResultFilter{
}
他继承了 FilterAttribute, IActionFilter, IResultFilter三个类,通常我们在Action逻辑之前需要处理一些功能,比如权限等,因此会自定义一个Filter,它继承于
ActionFilterAttribute ,然后再在ActionFilterAttribute 中重载由接口 IActionFilter, IResultFilter继承下来的函数
void OnActionExecuting(ActionExecutingContext filterContext)
void OnActionExecuted(ActionExecutedContext filterContext)
void OnResultExecuting(ResultExecutingContext filterContext)
void OnResultExecuted(ResultExecutedContext filterContext)

其中ActionFilterAttribute有两个属性,一个是继承FilterAttribute,另一个继承Attribute

Order 获取或者设置执行操作筛选器的顺序。 (继承自 FilterAttribute。)

TypeId 当在派生类中实现时,获取该 Attribute 的唯一标识符。 (继承自 Attribute。)

例如如下代码段:

[orderFilter(RoleId="2",Order=2)]
[UserFilter(UserId="3",Order=1)]
public ActionResult test() {
    return View();
}

程序在执行的顺序为:UserFilter->orderFilter->test

二:实例部分

了解上面的一些知识后,我们来看一下我设计的权限实例:
如果不知道用户,角色,组,权限之前的一些关系,建议你先看我上一篇“权限的基础知识”,这篇文章是我转过来的,觉得还不错,因为之前自己做完项目后没
分的很清楚,现在看完那篇文章,对号入座,才清楚原来我也是按照用户,角色,组,权限等这些关系来进行着 ^_^(如果下面对号入座的不对,请大家指正)
假设现在有4种功能权限: 添加功能、删除功能、发布功能、修改功能等。按照二进制01格式来设计,0表示没有该功能权限,1表示有该权限,
也就是说,按照顺序
          添加 删除 发布 修改
          1      1    1     1       如果只有修改功能 就是0001,
                      如果有添加及删除功能   就是1100,

将二进制转换为int数   添加功能:(1000=int数 8) 删除功能:(0100=int数 4) 发布功能:(0010=int数 2) 修改功能:(0001 =int数 1)
            这我可以理解为 -----权限
而每个用户拥有的功能(权限)是不一样的 ,可以有多种组合, 比如1001(添加及修改权限)  0011(发布及修改权限) 1111(全部权限)
            这我可以理解为-------组
而对不同用户我将他们的权限组合功能变为int 数存于user表的Permission(int)字段中,这样的话:(添加及修改权限1001=int数 9)
(发布及修改权限0011=int 数 3) (全部权限1111=int数 15)
            这我可以理解为--------角色
至于用户就是我们自己数据库里面的username了.

设置用户权限:只需要将所拥有功能权限的int数相加存入数据库就可;
查看用户权限:则需要先将Permission的int值解析为二进制数,然后再看为1 的位数的int数值与对应的功能值就可。
实现: 当用户登录的时候,先查看他的Permission的int值(就是角色),将角色解析为相应的组,将每组的权限int值载入用户主体的Roles,他是一个数组形式。
(因为有一种或多种功能权限)
然后在每个需要进行权限过滤的Action上加上自定义的Filter:即在重载的OnActionExecuting方法内判断是否当前用户的Roles里面存在该功能权限,如果存在,
则进入页面,否则跳到无权限页面。

下面就是代码了,继承ActionFilterAttribute类,并且重载OnActionExecuting方法:

复制代码

publicclass RoleFilter : ActionFilterAttribute {
        publicstring checkRole { get; set; }     //应传入的功能权限值
publicoverridevoid OnActionExecuting(ActionExecutingContext filterContext) {
            if(!string.IsNullOrEmpty(checkRole)) {
                if(!filterContext.HttpContext.User.Identity.IsAuthenticated) {    //判断用户是否已经登录,没登录跳转到登录页面,
string okurl = filterContext.HttpContext.Request.RawUrl;
                    string redirectUrl =string.Format("?ReturnUrl={0}", okurl);
                    string loginUrl = FormsAuthentication.LoginUrl + redirectUrl;
                    filterContext.Result =new RedirectResult(loginUrl);
                } else {  //已登录用户
bool isAuthorize = filterContext.HttpContext.User.IsInRole(checkRole);  
                    if(!isAuthorize)  //判断用户是否拥有checkRole权限,没有的话跳转到权限错误页。
                        filterContext.Result =new RedirectToRouteResult("Default", new RouteValueDictionary(new { Controller ="Account", Action ="AuthorizeError" }));
                }
            } else {
                thrownew InvalidOperationException("该用户没有指定角色,请联系管理员给予角色。");
            }
        }
    }

复制代码

在程序刚启动的时候如要读取用户角色的权限。才好做上面的比较:

复制代码

public MvcApplication() {
            AuthorizeRequest +=new EventHandler(MvcApplication_AuthorizeRequest);
        }

void MvcApplication_AuthorizeRequest(object sender, EventArgs e) {
            //获取当前用户的角色
if(HttpContext.Current.User.Identity.IsAuthenticated) {
          //下面这个方法是将role(int)转换为二进制 然后算个每个权限的int值 数组
                var roles = CMSPermissionController.Instance.PermissionIdList(HttpContext.Current.User.Identity.Name.Trim()).ToArray<string>();
                HttpContext.Current.User =new System.Security.Principal.GenericPrincipal(HttpContext.Current.User.Identity, roles);
            }
        }

复制代码

调用的过程为:

复制代码

//根据需要你也可以对整个Controller加【attribute】
[RoleFilter(checkRole ="2")]
    publicclass GroupController : Controller {
        public ActionResult Index() {
            return View();
        }

public ActionResult Create() {
            return View();
        }
}

//也可以对某个特定的Action添加
[RoleFilter(checkRole ="4")]
publicstring Delete(string RelaPath) {
//to do ...
}

复制代码

上面的代码基本上就可以实现了,在调试的过程中,曾经有个同事问,如果我要在Delete上也要检查checkRole="8"的时候你怎么办,我当时有点懵。。。没想
太多,就觉得那到底是先checkRole是4还是先checkRole是“8”呢,现在看来,不存在那样状况,  因为我定义的4,8等数字, 本身就是定死的权限,比如
添加 删除 发布 修改对应的权限数字是8,4,2,1;所以如果我们要对Delete本来是4的权限,来检查添加的权限8,业务逻辑上本身也是不存在的! O(∩_∩)O

还看到一篇关于权限的文章:是用当前的url来判断的,很值得学习,供以后研究:
http://www.cnblogs.com/legendxian/archive/2010/01/25/1655551.html

时间: 2024-08-02 14:43:17

MVC中权限的知识点及具体实现代码的相关文章

MVC中权限管理

权限管理,一般指根据系统设置的安全规则或者安全策略,用户可以访问而且只能访问自己被授权的资源,不多不少.权限管理几乎出现在任何系统里面,只要有用户和密码的系统.权限管理还是比较复杂的,有的固定到某个模块,某个操作,甚至是某个按钮,总之想要做好一个权限管理,真的很不容易,一直在探索当中,全当抛砖引玉:看到网上好多关于权限管理的文章,以前也写过简单的文章,今天楼主我也要总结整理一下自己的实现方法,毕竟一千个读者就有一千个哈姆雷特,说说自己的详细实现.基本设计和基本思想希望帮到入门的新人们.    

在ASP.NET MVC中实现基于URL的权限控制

本示例演示了在ASP.NET MVC中进行基于URL的权限控制,由于是基于URL进行控制的,所以只能精确到页.这种权限控制的优点是可以在已有的项目上改动极少的代码来增加权限控制功能,和项目本身的耦合度低,并且实现起来也比较简单.缺点是权限控制不够精确,不能具体到某一具体的按钮或者某一功能. 在数据库中新建2个表.PermissionItem表用于保存权限ID和页面路径的关系,一个权限ID可以有多个页面,一般同一个权限ID下的页面是为了实现同一个功能.PermissionList表用于保存用户所具

MVC中验证登录和权限

用mvc做后台管理系统,必然会要做登录和权限判断.这里是用mvc的ActionFilterAttribute特性. 具体如下: 声明一个CheckUser类,继承ActionFilterAttribute类 public class CheckUserFilter : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { base.OnActio

MVC5+EF6 入门完整教程11--细说MVC中仓储模式的应用

大家久等了. 本篇专题主要讲述MVC中的权限方案. 权限控制是每个系统都必须解决的问题,也是园子里讨论最多的专题之一. 前面的系列文章中我们用到了 SysUser, SysRole, SysUserRole 这几个示例表. 我们以此为基础,完成RBAC (基于角色的控制) 的核心功能. 在此给出我的最佳实践,最终的效果是针对任意一个Action或Controller,都可以根据配置的角色来控制访问权限. 完成此核心功能后,可以再往两方面扩展常用功能: 1. 可以根据 组织/用户/角色 的并集来控

MVC中ActionFilterAttribute用法并实现统一授权

MVC中ActionFilterAttribute经常用来处理权限或者统一操作时的问题. 先写一个简单的例子,如下: 比如现在有一个用户管理中心,而这个用户管理中心需要登录授权后才能进去操作或浏览信息,这个时候我们不可能每一个页面都写一遍权限的判断,这个时候就需要我们进行统一判断权限,那么怎么统一权限呢?如果你了解MVC那么下面的代码应该很容易看懂,否则还是先看一下MVC基础吧. 1.创建一个类(用来检查用户是否登录和用户权限)代码如下: // 过滤器    public class Membe

Asp.Net MVC中DropDownListFor的用法(转)

2016.03.04 扩展:如果 view中传入的是List<T>类型 怎么使用 DropList 既然是List<T> 那么我转化成 T  List<T>的第一个,最后一个不就是M吗? @Html.DropDownListFor(model=>model.First().Title, ViewData["Title"] as List<SelectListItem>, "标题", @"dropdown

ASP.NET MVC +EasyUI 权限设计(二)环境搭建

请注明转载地址:http://www.cnblogs.com/arhat 今天突然发现博客园出问题了,老魏使用了PC,手机,平板都访问博客园了,都是不能正常的访问,原因是不能加载CSS,也就是不能访问common.cnblogs.com这个域名,一直出现"Aborted",非常的郁闷. 页面就是这样子的,不知道为什么,难道是不是我的3个终端有问题吧,还是园子的服务器有问题呢?还是路由器的问题呢?到现在这个问题还没解决,郁闷死了!弄得心情非常的不爽. 好吧,不在说这个问题了,开始我们的正

关于ASP.NET MVC的权限认证的一些总结

最近在学ASP.NET MVC的权限认证的一些东西,上网搜索了一阵,发现网上的方法大多数是以下几类: 一.FormsAuthentication.SetAuthCookie(admin.Name, false)或者是FormsAuthenticationTicket 感受:感觉FormsAuthentication.SetAuthCookie这种方法重在检查是否有用户登录等,需要检查权限时,要调用this.User.Identity.IsAuthenticated方法来检查是否授权等,每次要检查

angular.js的路由和模板在asp.net mvc 中的使用

我们知道angular.js是基于mvc 的一款优秀js框架,它也有一套自己的路由机制,和asp.net mvc 路由不太一样.asp.net mvc 的路由是通过不同的URL到不同的controller然后交给controller去呈现视图.但是在angular.js则是需要提前指定一个module(ng-app),然后去定义路由规则,通过不同的URL,来告诉ng-app 去加载哪个页面.再渲染到ng-view.通过angular.js路由的使用,可以很容易实现页面的局部刷新.更加高效的去创建