zoukankan      html  css  js  c++  java
  • Asp.Net MVC Filter权限过滤使用说明

    相信对权限过滤大家都不陌生,用户要访问一个页面时,先对其权限进行判断并进行相应的处理动作。

    mvc中是如何实现权限验证的?

    mvc中是根据路由配置来请求控制器类中的一个方法

    在mvc框架中为程序员提供了一种过滤器机制

    通过过滤器,我们可以随心所欲的控制访问权限

    首先,我们可以自己添加一个过滤器

    添加一个类,名为MyFilter1Attribute

    并继承自ActionFilterAttribute类(注意,这里的ActionFilterAttribute的命名空间是System.Web.Mvc不要引用错了~)

    现在这个MyFilter1Attribute就是一个过滤器类了

    因为继承自ActionFilterAttribute类

    所以我们自己添加的MyFilter1Attribute就拥有了许多过滤方法

    我们对ActionFilterAttributeF12转到定义看一看里面有什么东西

    可以看到,这个ActionFilterAttribute是一个特性类(这就是人家为什么以Attribute结尾啦~)

    并且实现了两个很重要的接口IActionFilter,IResultFilter

    我们在转到定义看一下这两个接口中有什么

    可以看到

    这两个接口中各自定义了两个方法,而ActionFilterAttribute既然实现了它们,那么ActionFilterAttribute自然也会拥有这四个方法

    那么这四个方法是什么呢?

    前面我们说到过,ActionFilterAttribute其实是一个特性类

    什么是特性类?

    就比如实体验证的时候,为实体的字段贴上的标签Required,还有HttpPost、HttpGet等标签

    而我们自己添加的MyFilter1Attribute也是一个特性类

    这有什么用吗?

    等下你就知道了~

    现在先在MyFilter1Attribute中重写OnActionExecuting方法

    其实我们可以从这个方法的名字上大概推出这个方法是做什么的了

    没错,该方法会在action方法执行之前调用

    反之IActionFilter中的另一个方法--OnActionExecuted就是在action方法执行完毕之后调用

    public class MyFilter1Attribute:ActionFilterAttribute  
        {  
            //该方法会在action方法执行之前调用  
            public override void OnActionExecuting(ActionExecutingContext filterContext)  
            {  
                filterContext.HttpContext.Response.Write("我是OnActionExecuting,我在action方法调用钱执行<br/>");  
                base.OnActionExecuting(filterContext);  
            }  
      
            //该方法会在action方法执行之后调用  
            public override void OnActionExecuted(ActionExecutedContext filterContext)  
            {  
                filterContext.HttpContext.Response.Write("我是OnActionExecuted,我在action方法调用后执行<br/>");  
                base.OnActionExecuted(filterContext);  
            }  
      
        }  

    在Home控制器中添加一个action方法

    [MyFilter1]  
    public void FilterTest()  
    {  
         Response.Write("我是action方法,在这里执行了~~</br>");  
    } 

    这时候看到了吗?

    要在一个action方法中使用一个过滤器

    只要在该方法上贴一个过滤器的标签就ok~ 
    生成运行,结果如下:

    但是,有时候我们会有这样的一需求:

    在过滤器中当遇到了贴了某某标签的action方法就跳过不进行验证

    这怎么办呢?

    可以通过filterContext的ActionDescriptor属性类完成这易操作

    ActionDescriptor顾名思义,action方法的描述着

    在ActionDescriptor中我们可以拿到相应的action方法信息,甚至还可以拿到一个控制器描述着ControllerDescriptor

    代码如下:

    //该方法会在action方法执行之前调用  
            public override void OnActionExecuting(ActionExecutingContext filterContext)  
            {  
                filterContext.HttpContext.Response.Write("我是OnActionExecuting,我在action方法调用前执行<br/>");  
                //判断该action方法时候有贴上MyFilter1Attribute标签  
                if (filterContext.ActionDescriptor.IsDefined(typeof (MyFilter1Attribute),false))  
                {  
                    //如果有,为该action方法直接返回ContentResult,则该action方法在这里就有了返回值,相当于在这里就结束了,不会在去执行之后的方法,如:OnActionExecuted等  
                    filterContext.Result = new ContentResult();  
                }  
                base.OnActionExecuting(filterContext);  
            } 

    结果如图:

     

    可以看到,action方法中和OnActionExecuted中的Response.Write都没有被执行,也就是说,该action方法被跳过了

    之前我们使用的是IActionFilter接口中的方法

    接下来介绍IResultFilter接口方法

     
    //在action方法返回结果之后执行  
            public override void OnResultExecuting(ResultExecutingContext filterContext)  
            {  
                filterContext.HttpContext.Response.Write("我是OnActionExecuting,我action方法返回结果之前执行<br/>");  
                base.OnResultExecuting(filterContext);  
            }  
      
            //在action方法返回结果之前前执行  
            public override void OnResultExecuted(ResultExecutedContext filterContext)  
            {  
                filterContext.HttpContext.Response.Write("我是OnResultExecuted,我在action方法返回结果之后执行<br/>");  
                base.OnResultExecuted(filterContext);  
            }  

    IResultFilter中同样也有两个方法

    我们将FilterTest改为下面代码:

    [MyFilter1]  
            public ActionResult FilterTest()  
            {  
                Response.Write("我是action方法的Response.Write,在这里执行了~~</br>");  
                return View();  
            }  

    并添加视图如下:

    <body>  
        <div>  
            我是FilterTest的视图,在这里执行action方法~~  
        </div>  
    </body>  

    生成并运行,结果图:

      

    可以看到,IResultFilter接口中的方法和IActionFilter方法的区别就是执行位置不一样

    但是呢,mvc框架中还有一个过滤器

    他就是权限过滤器AuthorizeAttribute

    该过滤器在所有action方法过滤器之前执行,也就是说,提供了一个可以超前验证的方法

    我们在添加一个新的过滤器类,并继承自AuthorizeAttribute

    重写其OnAuthorization方法如下:

    这里需要注意,把基类的OnAuthorization方法去掉,因为我们并不需要,而且留着可能会出现一些错误异常

    public class MyFilter2Attribute:AuthorizeAttribute  
        {  
            //在所有action方法过滤器之前执行  
            public override void OnAuthorization(AuthorizationContext filterContext)  
            {  
                filterContext.HttpContext.Response.Write("我是OnAuthorization,在所有action方法过滤器之前执行<br/>");  
                //base.OnAuthorization(filterContext);  
            }  
        }  

    action代码

    [MyFilter1]  
            [MyFilter2]  
            public ActionResult FilterTest()  
            {  
                Response.Write("我是action方法的Response.Write,在这里执行了~~</br>");  
                return View();  
            } 
     

    为FilterTest方法在贴上MyFilter2标签

    运行:

     

    有图有证据~

    如此一来

    我们就可以根据需要选择合适的方法进行权限验证

    但是这时候又有问题了

    什么问题呢?

    这个特性是贴在action方法上面的

    如果我控制器中所有的action方法都要进行验证怎么办?

    难道每个action方法都贴一遍吗?

    如果我程序中的所有控制器中的所有action方法都需要验证呢?

    放心~

    懒惰的程序员们是不会去做这种傻事的~

    如果一个控制器中的所有方法都需要验证

    那么我们可以再控制器类上统一贴上标签,如下:

    这样一来该控制器中的所有action方法都会进行验证

    那么如果每个控制器类都要验证呢?

    这个时候我们就需要打开App_Start文件夹了

    看到一个FilterConfig类了吗

    双击打开FilterConfig.cs

    我们可以再这里进行添加全局的过滤器,比如:

    最后我们在介绍一个异常处理的过滤器

    添加一个过滤器类,并继承自HandleErrorAttribute

    public class MyFilter3Attribute:HandleErrorAttribute  
       {  
           //在程序中任何地方出现异常都会执行  
           public override void OnException(ExceptionContext filterContext)  
           {  
               //获取异常对象  
               Exception ex = filterContext.Exception;  
               //记录错误日志  
               //导向友好错误界面  
               filterContext.Result = new RedirectResult("/Home/Index");  
               //重要!!告诉系统异常已处理!!如果没有这个步骤,系统还是会按照正常的异常处理流程走  
               filterContext.ExceptionHandled = true;  
               //base.OnException(filterContext);  
           }  
       }  
     

    注意,这里基类的OnException也是不需要的

    异常处理的过滤器要放在全局/App_Start/FilterConfig.cs中

    filters.Add(new MyFilter3Attribute());  

    ok,搞定~

  • 相关阅读:
    DS博客作业03--栈和队列
    DS博客作业02--线性表
    DS博客作业01--日期抽象数据类型设计与实现
    C语言博客作业06--结构体&文件
    DS博客作业08--课程总结
    DS博客作业07--查找
    DS博客作业06--图
    DS博客作业05--树
    DS博客大作业--树 (陈梓灿组)
    DS博客作业03--栈和队列
  • 原文地址:https://www.cnblogs.com/webapi/p/5669057.html
Copyright © 2011-2022 走看看