AuthorizeFilter筛选器

在Action的执行中包括两个重要的部分,一个是Action方法本身逻辑代码的执行,第二个就是Action方法的筛选器的执行。

MVC4中筛选器都是以AOP(面向方面编程)的方式来设计的,通过对Action方法上标注相应的Attribute标签来实现。MVC4提供了四种筛选器,分别为:AuthorizationFilter、ActionFilter、ExceptionFilter和ResultFilter,他们分别对应了四个筛选器接口IAuthorizationFilter、IActionFilter、IExceptionFilter和IResultFilter。

这四种筛选器都有派生于一个公共的类FilterAttribute,该类指定了筛选器的执行顺序Order和是否允许多个应用AllowedMultiple。这四种筛选器默认的执行顺序为最先进行授权筛选,最后进行异常处理,中间则是ActionFilter和ResultedFilter。

下面是抽象类FilterAttribute的类图

下面我们来具体列举一下各个筛选器的作用和实现

从字面上我们就能看出这是对Controller或Action方法授权的筛选器,即在Controller或Action方法执行前,首先会先执行该筛选器,若通过,才会继续执行。下面是此筛选器的简单类图

AuthorizeAttribute为最终授权筛选器的实现者,它实现了IAuthorizationFilter接口和FilterAttribute抽象类,接口中的OnAuthorization(AuthorizationContext filterContext)方法是最终验证授权的逻辑(其中AuthorizationContext是继承了ControllerContext类)

  1. protected virtual bool AuthorizeCore(HttpContextBase httpContext)
  2. {
  3. if (httpContext == null)
  4. {
  5. throw new ArgumentNullException("httpContext");
  6. }
  7. IPrincipal user = httpContext.User;
  8. if (!user.Identity.IsAuthenticated)
  9. {
  10. return false;
  11. }
  12. if (_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase))
  13. {
  14. return false;
  15. }
  16. if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole))
  17. {
  18. return false;
  19. }
  20. return true;
  21. }

AuthorizeCore方法是最终OnAuthorization()方法调用的最终逻辑,从代码可以看出,当同时指定了users和roles时,两者只有同时满足条件时才可以验证授权通过。如

  1. [Authorize(Users="zhangsan", Roles="Admin")]
  2. public ActionResult ActionMethod()
  3. {
  4. }

则只有用户zhangsan,且用户属于Admin角色时才能验证授权通过。

若验证不通过时,OnAuthorization方法内部会调用HandleUnauthorizedRequest

虚方法进行处理,代码如下:

  1. protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext)
  2. {
  3. // Returns HTTP 401 - see comment in HttpUnauthorizedResult.cs.
  4. filterContext.Result = new HttpUnauthorizedResult();
  5. }

该方法设置了参数上下文中ActionResult的值,用于供View展示。

我们可以自定义Authorize筛选器,由于OnAthurization()、AuthorizeCore()和HandleUnauthorizedRequest()方法都是虚方法,我们自定义的Authorize筛选器只需要继承AuthorizeAttribute类,重写以上三种方法,这样就可以自定义自己的验证规则和验证失败时的处理逻辑了。

IAuthorizationFilter还有其他类型的实现类,如RequireHttpsAttribute、ValidateInputAttribute都是实现了OnAuthorization()方法,来完成各自筛选器处理的。

ExceptionFilter过滤器

该筛选器是在系统出现异常时触发,可以对抛出的异常进行处理。所有的ExceptionFilter筛选器都是实现自IExceptionFilter接口

  1. public interface IExceptionFilter
  2. {
  3. void OnException(ExceptionContext filterContext);
  4. }

实现OnException方法来实现对异常的自定义处理

MVC4中实现了默认的异常处理机制,源码如下

  1. public virtual void OnException(ExceptionContext filterContext)
  2. {
  3. if (filterContext == null)
  4. {
  5. throw new ArgumentNullException("filterContext");
  6. }
  7. if (filterContext.IsChildAction)
  8. {
  9. return;
  10. }
  11. // If custom errors are disabled, we need to let the normal ASP.NET exception handler
  12. // execute so that the user can see useful debugging information.
  13. if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
  14. {
  15. return;
  16. }
  17. Exception exception = filterContext.Exception;
  18. // If this is not an HTTP 500 (for example, if somebody throws an HTTP 404 from an action method),
  19. // ignore it.
  20. if (new HttpException(null, exception).GetHttpCode() != 500)
  21. {
  22. return;
  23. }
  24. if (!ExceptionType.IsInstanceOfType(exception))
  25. {
  26. return;
  27. }
  28. string controllerName = (string)filterContext.RouteData.Values["controller"];
  29. string actionName = (string)filterContext.RouteData.Values["action"];
  30. HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
  31. filterContext.Result = new ViewResult
  32. {
  33. ViewName = View,
  34. MasterName = Master,
  35. ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
  36. TempData = filterContext.Controller.TempData
  37. };
  38. filterContext.ExceptionHandled = true;
  39. filterContext.HttpContext.Response.Clear();
  40. filterContext.HttpContext.Response.StatusCode = 500;
  41. // Certain versions of IIS will sometimes use their own error page when
  42. // they detect a server error. Setting this property indicates that we
  43. // want it to try to render ASP.NET MVC's error page instead.
  44. filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
  45. }
Application_Start中将HandleErrorAttribute添加到全局筛选器GlobalFilterCollection中,系统即会对异常进行对应的处理。
我们现在实现一个自定义的异常处理筛选器,在处理完后记录异常信息至日志文件中  
  1. public class MyExceptionHandleAttribute : HandleErrorAttribute
  2. {
  3. public MyExceptionHandleAttribute()
  4. : base()
  5. {
  6. }
  7. public void OnException(ExceptionContext filterContext)
  8. {
  9. base.OnException(filterContext);
  10. //记录日志
  11. log.Info(filterContext.Exception);
  12. }
  13. }
在GlobalFilterCollection添加MyExceptionHandleAttribute 即可使用自定义的异常筛选器来处理

ActionFilter筛选器

ActionFilter筛选器是在Action方法执行前后会触发,主要用于在Action执行前后处理一些相应的逻辑。ActionFilter的筛选器都继承于ActionFilterAttribute抽象类,而它实现了IActionFilter、IResultFilter和FilterAttribute类,结构如下

因此自定义ActionFilter筛选器只要继承ActionFilterAttribute,实现其中的方法即可。

我们来举一个简单的例子,获取Action方法的执行时长,代码如下

  1. public class DefaultController : Controller
  2. {
  3. [ActionExecTimeSpan]
  4. public ActionResult DoWork()
  5. {
  6. return View();
  7. }
  8. }
  9. public class ActionExecTimeSpanAttribute : ActionFilterAttribute
  10. {
  11. private const string executeActionTimeKey = "ActionExecBegin";
  12. public override void OnActionExecuting(ActionExecutingContext filterContext)
  13. {
  14. base.OnActionExecuting(filterContext);
  15. //记录开始执行时间
  16. filterContext.HttpContext.Items[executeActionTimeKey] = DateTime.Now;
  17. }
  18. public override void OnActionExecuted(ActionExecutedContext filterContext)
  19. {
  20. //计算执行时间,并记录日志
  21. if (filterContext.HttpContext.Items.Contains(executeActionTimeKey))
  22. {
  23. DateTime endTime = DateTime.Now;
  24. DateTime beginTime = Convert.ToDateTime(filterContext.HttpContext.Items[executeActionTimeKey]);
  25. TimeSpan span = endTime - beginTime;
  26. double execTimeSpan = span.TotalMilliseconds;
  27. log.Info(execTimeSpan + "毫秒");
  28. }
  29. //
  30. base.OnActionExecuted(filterContext);
  31. }
  32. }

ResultFilter筛选器

ResultFilter筛选器是对Action方法返回的Result结果进行执行时触发的。它也分执行前和执行后两个段执行

所有的ResultFilter都实现了IResultFilter接口和FilterAttribute类,看一下接口定义

  1. public interface IResultFilter
  2. {
  3. void OnResultExecuting(ResultExecutingContext filterContext);
  4. void OnResultExecuted(ResultExecutedContext filterContext);
  5. }
其中OnResultExecuting和OnResultExecuted方法分别是在Result执行前、后(页面展示内容生成前、后)触发。
使用ResultFilter筛选器最典型的应用就是页面静态化,我们以后在其他文章中在对此进行详细讲解
学习什么时候都不晚,从现在起我们一起

MVC四大筛选器—ActionFilter&ResultedFilter的更多相关文章

  1. MVC四大筛选器—AuthorizeFilter

    在Action的执行中包括两个重要的部分,一个是Action方法本身逻辑代码的执行,第二个就是Action方法的筛选器的执行. MVC4中筛选器都是以AOP(面向方面编程)的方式来设计的,通过对Act ...

  2. MVC四大筛选器—ExceptionFilter

    该筛选器是在系统出现异常时触发,可以对抛出的异常进行处理.所有的ExceptionFilter筛选器都是实现自IExceptionFilter接口 public interface IExceptio ...

  3. 在ASP.NET MVC中的四大筛选器(Filter)及验证实现

    http://www.cnblogs.com/artech/archive/2012/08/06/action-filter.html http://www.cnblogs.com/ghhlyy/ar ...

  4. MVC常用筛选器Filter

    1.ActionFilterAttribute using System; using System.Collections.Generic; using System.Diagnostics; us ...

  5. mvc 筛选器

    之前公司中,运用ActionFilterAttribute特性实现用户登录信息的验证,没事看了看,留下点东西备忘. 好的,瞅这玩意一眼就大概能猜到这货是干嘛的了吧,没错,action过滤器.其实就是A ...

  6. Asp.Net mvc筛选器中返回信息中断操作

    在mvc中,使用response.end()或Response.Redirect("url"); 是无法阻止请求继续往下执行的.如果在action中,可以我们可以使用return ...

  7. Asp.Net MVC 页面代码压缩筛选器-自定义删除无效内容

    Asp.Net MVC 页面代码压缩筛选器 首先定义以下筛选器,用于代码压缩. /*页面压缩 筛选器*/ public class WhiteSpaceFilter : Stream { privat ...

  8. 基础教程:ASP.NET Core 2.0 MVC筛选器

    问题 如何在ASP.NET Core的MVC请求管道之前和之后运行代码. 解 在一个空的项目中,更新 Startup 类以添加MVC的服务和中间件. publicvoid ConfigureServi ...

  9. 如何在ASP.NET MVC为Action定义筛选器

    在ASP.NET MVC中,经常会用到[Required]等特性,在MVC中,同样可以为Action自定义筛选器,来描述控制器所遵守的规则. 首先,我们在ASP.NET MVC项目中定义一个TestC ...

随机推荐

  1. # 2019-2020-3 《Java 程序设计》第四周总结

    2019-2020-3 <Java 程序设计>第四周知识总结 第五章:继承 1.定义继承关系的语法结构: [修饰符] class 子类名 extends 父类名 { 类体定义 } 父类中应 ...

  2. django的母板系统

    一.母板渲染语法 1.变量 {{ 变量 }} 2.逻辑 {% 逻辑语 %} 二.变量 在母板中有变量时,母板引擎会去反向解析找到这个传来的变量,然后替换掉. .(点),在母板中是深度查询据点符,它的查 ...

  3. Awesome Python 中文版

    Awesome Python ,这又是一个 Awesome XXX 系列的资源整理,由 vinta 发起和维护.内容包括:Web框架.网络爬虫.网络内容提取.模板引擎.数据库.数据可视化.图片处理.文 ...

  4. explain 类型分析

    all 全表扫描 ☆ index 索引全扫描 ☆☆ range 索引范围扫描,常用语<,<=,>=,between等操作 ☆☆☆ ref 使用非唯一索引扫描或唯一索引前缀扫描,返回单 ...

  5. OCP 12c考试题,062题库出现大量新题-第20道

    choose three Your database is configured for ARCHIVELOG mode, and a daily full database backup is ta ...

  6. typescript handbook 学习笔记4

    概述 这是我学习typescript的笔记.写这个笔记的原因主要有2个,一个是熟悉相关的写法:另一个是理清其中一些晦涩的东西.供以后开发时参考,相信对其他人也有用. 学习typescript建议直接看 ...

  7. 《机器学习实战(基于scikit-learn和TensorFlow)》第四章内容的学习心得

    本章主要讲训练模型的方法. 线性回归模型 闭式方程:直接计算最适合训练集的模型参数 梯度下降:逐渐调整模型参数直到训练集上的成本函数调至最低,最终趋同与第一种方法计算出的参数 首先,给出线性回归模型的 ...

  8. springmvc与fastjson的整合,注解@RequestBody的使用

    项目内容用的是jetty框架,传输数据格式是json格式,有一天我心血来潮,把项目又搭建了一次,完了,卡在了数据传输的格式上,明明原来框架直接用fastjson,但是我用就是不对,总是报fastjso ...

  9. C# 获取Header中的token值

    public CurrentUser currentUser { get { CurrentUser result = new CurrentUser(); //jwt 解密token IJsonSe ...

  10. HW2017笔试编程题

    一.写一个转换字符串的函数 1.题目描述 将输入字符串中下标为偶数的字符连成一个新的字符串输出,需要注意两点: (1)如果输入字符串的长度超过20,则转换失败,返回“ERROR!”字符串: (2)输入 ...