APS.NET MVC + EF (11)---過濾器

過濾器本質就是對動做方法的執行過程進行干預,這種干預能夠影響動做方法執行的各個過程。ASP.NET MVC 提供了4種類型的接口,並在接口中定義了各類成員,表明代碼執行的各個階段,這些接口和成員如表11-1所示。 html

表11-1 常見過濾器接口 web

過濾器類型數據庫

接口app

默認實現ide

描述函數

Action加密

IActionFilterspa

ActionFilterAttribute設計

在動做方法以前及以後運行日誌

Result

IResultFilter

ActionFilterAttribute

在動做結果被執行以前和以後運行

AuthorizationFilter

IAuthorizationFilter

AuthorizeAttribute

首先運行,在任何其它過濾器或動做方法以前

Execption

IExceptionFilter

HandleErrorAttribute

只在另外一個過濾器、動做方法、動做結果彈出異常時運行

   

當動做方法同時應用了繼承自這些特性的過濾器後,實際的執行過程如圖11-1所示。

 

   

 

圖11-1 過濾器執行過程

   

圖11-1中流程並無列出 OnException() 方法的執行時機,事實上,在執行流程中只要任何環節出現異常,就會執行 OnException()方法。

11.1 過濾器的使用

ASP.NET MVC 的這種過濾器機制,實際是體現了一種 AOP(面向切面) 設計思想,當須要爲動做方法進行干預時,不須要變更動做方法內部的代碼,就能夠擴張橫向的行爲。在實際開發中,只須要繼承這些接口,實現自定義的特性,並在動做方法上應用自定義的特性,就能夠擴展動做方法的能力。實現自定義的過濾器特性,須要知足兩個要求。一是實現表11-1中任意的接口,二是繼承FilterAttribute,標識它是一個過濾器。接下來介紹自定義過濾器的用法。

   

11.1.1 Action 過濾器

在ASP.NET MVC 項目中建立文件夾Filter,而後新建類MyActionFilterAttribute(爲了遵循默認的約定,名稱以Attribute結尾),繼承自ActionFilterAttribute類。ActionFilterAttribute類有以下4個方法。

public virtual void OnActionExecuted(ActionExecutedContext filterContext);

public virtual void OnActionExecuting(ActionExecutingContext filterContext);

public virtual void OnResultExecuted(ResultExecutedContext filterContext);

public virtual void OnResultExecuting(ResultExecutingContext filterContext);

MyActionFilterAttribute.cs 類的代碼如示例1所示。

示例1

public class MyActionFilterAttribute : ActionFilterAttribute

{

//Action執行以前

public override void OnActionExecuting(ActionExecutingContext filterContext)

{

//一、獲取請求的類名和方法名

string strController = filterContext.RouteData.Values["controller"].ToString();

string strAction = filterContext.RouteData.Values["action"].ToString();

   

//二、用另外一種方式獲取請求的類名和方法名

string strController2 = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;

string strAction2 = filterContext.ActionDescriptor.ActionName;

   

filterContext.HttpContext.Response.Write("控制器:" + strController + "<br/>");

filterContext.HttpContext.Response.Write("控制器:" + strController2 + "<br/>");

filterContext.HttpContext.Response.Write("Action:" + strAction + "<br/>");

filterContext.HttpContext.Response.Write("Action:" + strAction2 + "<br/>");

filterContext.HttpContext.Response.Write("Action執行前:" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "<br/>");

base.OnActionExecuting(filterContext);

   

}

//Action執行以後

public override void OnActionExecuted(ActionExecutedContext filterContext)

{

filterContext.HttpContext.Response.Write("Action執行後:" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "<br/>");

base.OnActionExecuted(filterContext);

}

}

對於過濾器,咱們能夠把它們加在3個地方,一個是控制器上面(控制器下面的全部Action),一個是Action上面(指定標識的Action),另外一個就是全局位置(全部控制器中的Action)

在控制器上代碼以下:

[MyActionFilter]

public ActionResult Index()

{

return View();

}

11.1.2 Result 過濾器

在Filter文件夾中新建MyResultFilterAttribute類,繼承ActionFilterAttribute。如示例2所示。

示例2

public class MyResultAttribute: ActionFilterAttribute

{

// 加載"視圖"前執行

public override void OnResultExecuting(ResultExecutingContext filterContext)

{

filterContext.HttpContext.Response.Write("加載視圖前執行 OnResultExecuting" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "<br/>");

base.OnResultExecuting(filterContext);

}

// 加載"視圖"後執行

public override void OnResultExecuted(ResultExecutedContext filterContext)

{

filterContext.HttpContext.Response.Write("加載視圖後執行 OnResultExecuted" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "<br/>");

base.OnResultExecuted(filterContext);

}

}

這裏把MyResultFilter過濾器加在控制器上面,至關於給Home控制器中的全部的Action方法添加了MyResultFilter過濾器。以下代碼所示。

[MyResultFilter]

public class HomeController : Controller

{

[MyActionFilter]

public ActionResult Index()

{

return View();

}

}

   

11.1.3 AuthorizeAttribute過濾器

建立MyAuthorizeAttribute類,繼承AuthorizeAttribute類。如示例3所示。

示例3

public class MyAuthorizeAttribute: AuthorizeAttribute

{

public override void OnAuthorization(AuthorizationContext filterContext)

{

filterContext.HttpContext.Response.Write("OnAuthorization<br/>");

//註釋掉父類方法,

//由於父類裏的OnAuthorization方法會調用ASP.NET的受權驗證機制

//base.OnAuthorization(filterContext);

}

}

在控制器Home中的Index上添加MyAuthorize過濾器。

[MyActionFilter]

[MyAuthorize]

public ActionResult Index()

{

return View();

}

一般Authorize過濾器也是在全局過濾器上面的,主要用來作登陸驗證或者權限驗證,在App_Start目錄下的FilterConfig類的RegisterGlobalFilters方法中添加:

public class FilterConfig

{

public static void RegisterGlobalFilters(GlobalFilterCollection filters)

{

filters.Add(new HandleErrorAttribute());

//添加全局受權過濾器

filters.Add(new MyAuthorizeAttribute());

}

}

在全局中註冊過濾器,則全部控制器的全部行爲(Action)都會執行這個過濾器。

   

11.1.4 Exception過濾器

建立MyHandleErrorAttribute類,繼承HandleErrorAttribute類。如示例4所示。

示例4

public class MyHandleErrorAttribute: HandleErrorAttribute

{

public override void OnException(ExceptionContext filterContext)

{

//一、獲取異常對象

Exception ex = filterContext.Exception;

//二、記錄異常日誌 (將錯誤信息利用IO保存到文件)

 

//三、重定向友好頁面

filterContext.Result = new RedirectResult("~/error.html");

//四、標記異常已經處理完畢

filterContext.ExceptionHandled = true;

 

base.OnException(filterContext);

}

}

在Action上面添加MyHandleError過濾器,以下所示。

[MyHandleError]

public ActionResult GetErr()

{

int a = 0;

int b = 1 / a;

return View();

}

運行會自動跳轉到error.html頁面。

若是頁面沒有跳轉,就須要去Web.config配置文件中的<system.web>節點下面添加以下配置節點,開啓自定義錯誤:

<customErrors mode="On"></customErrors>

   

一般這樣的異常處理是放在全局過濾器上面的,只要任意Action方法報錯就會執行MyHandleError過濾器中的代碼。

修改App_Start目錄下面的FilterConfig類:

public class FilterConfig

{

public static void RegisterGlobalFilters(GlobalFilterCollection filters)

{

//添加全局受權過濾器

filters.Add(new MyAuthorizeAttribute());

//添加全局異常處理過濾器

filters.Add(new MyHandleErrorAttribute());

}

}

Global.asax下的代碼:

public class MvcApplication : System.Web.HttpApplication

{

protected void Application_Start()

{

App_Start.AutoMapperConfig.Config();

   

AreaRegistration.RegisterAllAreas();

FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

RouteConfig.RegisterRoutes(RouteTable.Routes);

BundleConfig.RegisterBundles(BundleTable.Bundles);

}

}

   

11.2 基於Form的身份驗證

   

身份驗證流程

1、用戶登陸

  一、驗證表單:ModelState.IsValid

  二、驗證用戶名和密碼:經過查詢數據庫驗證

  三、若是用戶名和密碼正確,則在客戶端保存Cookie以保存用戶登陸狀態:SetAuthCookie

    1):從數據庫中查出用戶名和一些必要的信息,並把額外信息保存到UserData中

    2):把用戶名和UserData保存到 FormsAuthenticationTicket 票據中

    3):對票據進行加密 Encrypt

    4):將加密後的票據保存到Cookie發送到客戶端

  四、跳轉到登陸前的頁面

2、驗證登陸

  一、在Global中註冊PostAuthenticateRequest事件函數,用於解析客戶端發過來的Cookie數據

    1):經過 HttpContext.Current.User.Identity 判斷用戶是否登陸(FormsIdentity,IsAuthenticated,AuthenticationType)

    2):從HttpContext 的Request的Cookie中解析出Value,解密獲得 FormsAuthenticationTicket 獲得UserData

  二、角色驗證

    在Action加入 Authorize特性,能夠進行角色驗證

    在 HttpContext.Current.User 的 IsInRole 方法進行角色認證(須要重寫)

相關文章
相關標籤/搜索