AuthorizeFilter篩選器
在Action的執行中包括兩個重要的部分,一個是Action方法自己邏輯代碼的執行,第二個就是Action方法的篩選器的執行。html
MVC4中篩選器都是以AOP(面向方面編程)的方式來設計的,經過對Action方法上標註相應的Attribute標籤來實現。MVC4提供了四種篩選器,分別爲:AuthorizationFilter、ActionFilter、ExceptionFilter和ResultFilter,他們分別對應了四個篩選器接口IAuthorizationFilter、IActionFilter、IExceptionFilter和IResultFilter。編程
這四種篩選器都有派生於一個公共的類FilterAttribute,該類指定了篩選器的執行順序Order和是否容許多個應用AllowedMultiple。這四種篩選器默認的執行順序爲最早進行受權篩選,最後進行異常處理,中間則是ActionFilter和ResultedFilter。ide
下面是抽象類FilterAttribute的類圖post

下面咱們來具體列舉一下各個篩選器的做用和實現學習
從字面上咱們就能看出這是對Controller或Action方法受權的篩選器,即在Controller或Action方法執行前,首先會先執行該篩選器,若經過,纔會繼續執行。下面是此篩選器的簡單類圖ui

AuthorizeAttribute爲最終受權篩選器的實現者,它實現了IAuthorizationFilter接口和FilterAttribute抽象類,接口中的OnAuthorization(AuthorizationContext filterContext)方法是最終驗證受權的邏輯(其中AuthorizationContext是繼承了ControllerContext類)this
-
protected virtual bool AuthorizeCore(HttpContextBase httpContext)
-
-
-
-
throw new ArgumentNullException("httpContext");
-
-
-
IPrincipal user = httpContext.User;
-
if (!user.Identity.IsAuthenticated)
-
-
-
-
-
if (_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase))
-
-
-
-
-
if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole))
-
-
-
-
-
-
AuthorizeCore方法是最終OnAuthorization()方法調用的最終邏輯,從代碼能夠看出,當同時指定了users和roles時,二者只有同時知足條件時才能夠驗證受權經過。如url
-
[
Authorize(Users="zhangsan", Roles="Admin")]
-
public ActionResult ActionMethod()
-
-
則只有用戶zhangsan,且用戶屬於Admin角色時才能驗證受權經過。spa
若驗證不經過時,OnAuthorization方法內部會調用HandleUnauthorizedRequest
虛方法進行處理,代碼以下:debug
-
protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext)
-
-
-
filterContext.Result =
new HttpUnauthorizedResult();
-
該方法設置了參數上下文中ActionResult的值,用於供View展現。
咱們能夠自定義Authorize篩選器,因爲OnAthurization()、AuthorizeCore()和HandleUnauthorizedRequest()方法都是虛方法,咱們自定義的Authorize篩選器只須要繼承AuthorizeAttribute類,重寫以上三種方法,這樣就能夠自定義本身的驗證規則和驗證失敗時的處理邏輯了。
IAuthorizationFilter還有其餘類型的實現類,如RequireHttpsAttribute、ValidateInputAttribute都是實現了OnAuthorization()方法,來完成各自篩選器處理的。
該篩選器是在系統出現異常時觸發,能夠對拋出的異常進行處理。全部的ExceptionFilter篩選器都是實現自IExceptionFilter接口
-
public interface IExceptionFilter
-
-
void OnException(ExceptionContext filterContext);
-
實現OnException方法來實現對異常的自定義處理
MVC4中實現了默認的異常處理機制,源碼以下
-
public virtual void OnException(ExceptionContext filterContext)
-
-
if (filterContext == null)
-
-
throw new ArgumentNullException("filterContext");
-
-
if (filterContext.IsChildAction)
-
-
-
-
-
-
-
if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
-
-
-
-
-
Exception exception = filterContext.Exception;
-
-
-
-
if (new HttpException(null, exception).GetHttpCode() != 500)
-
-
-
-
-
if (!ExceptionType.IsInstanceOfType(exception))
-
-
-
-
-
string controllerName = (string)filterContext.RouteData.Values["controller"];
-
string actionName = (string)filterContext.RouteData.Values["action"];
-
HandleErrorInfo model =
new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
-
filterContext.Result =
new ViewResult
-
-
-
-
ViewData =
new ViewDataDictionary<HandleErrorInfo>(model),
-
TempData = filterContext.Controller.TempData
-
-
filterContext.ExceptionHandled =
true;
-
filterContext.HttpContext.Response.Clear();
-
filterContext.HttpContext.Response.StatusCode =
500;
-
-
-
-
-
filterContext.HttpContext.Response.TrySkipIisCustomErrors =
true;
-
Application_Start中將HandleErrorAttribute添加到全局篩選器GlobalFilterCollection中,系統即會對異常進行對應的處理。
咱們如今實現一個自定義的異常處理篩選器,在處理完後記錄異常信息至日誌文件中
-
public class MyExceptionHandleAttribute : HandleErrorAttribute
-
-
public MyExceptionHandleAttribute()
-
-
-
-
-
public void OnException(ExceptionContext filterContext)
-
-
base.OnException(filterContext);
-
-
log.Info(filterContext.Exception);
-
-
在GlobalFilterCollection添加MyExceptionHandleAttribute 便可使用自定義的異常篩選器來處理
ActionFilter篩選器
ActionFilter篩選器是在Action方法執行先後會觸發,主要用於在Action執行先後處理一些相應的邏輯。ActionFilter的篩選器都繼承於ActionFilterAttribute抽象類,而它實現了IActionFilter、IResultFilter和FilterAttribute類,結構以下

所以自定義ActionFilter篩選器只要繼承ActionFilterAttribute,實現其中的方法便可。
咱們來舉一個簡單的例子,獲取Action方法的執行時長,代碼以下
-
public class DefaultController : Controller
-
-
-
public ActionResult DoWork()
-
-
-
-
-
-
public class ActionExecTimeSpanAttribute : ActionFilterAttribute
-
-
private const string executeActionTimeKey = "ActionExecBegin";
-
-
public override void OnActionExecuting(ActionExecutingContext filterContext)
-
-
base.OnActionExecuting(filterContext);
-
-
filterContext.HttpContext.Items[executeActionTimeKey] = DateTime.Now;
-
-
-
public override void OnActionExecuted(ActionExecutedContext filterContext)
-
-
-
if (filterContext.HttpContext.Items.Contains(executeActionTimeKey))
-
-
DateTime endTime = DateTime.Now;
-
DateTime beginTime = Convert.ToDateTime(filterContext.HttpContext.Items[executeActionTimeKey]);
-
TimeSpan span = endTime - beginTime;
-
double execTimeSpan = span.TotalMilliseconds;
-
log.Info(execTimeSpan +
"毫秒");
-
-
-
base.OnActionExecuted(filterContext);
-
-
ResultFilter篩選器
ResultFilter篩選器是對Action方法返回的Result結果進行執行時觸發的。它也分執行前和執行後兩個段執行
全部的ResultFilter都實現了IResultFilter接口和FilterAttribute類,看一下接口定義
-
public interface IResultFilter
-
-
void OnResultExecuting(ResultExecutingContext filterContext);
-
-
void OnResultExecuted(ResultExecutedContext filterContext);
-
其中OnResultExecuting和OnResultExecuted方法分別是在Result執行前、後(頁面展現內容生成前、後)觸發。
使用ResultFilter篩選器最典型的應用就是頁面靜態化,咱們之後在其餘文章中在對此進行詳細講解
學習何時都不晚,從如今起咱們一塊兒