天天看點

ASP.NET MVC Filters 4種預設過濾器的使用【附示例】

過濾器(Filters)的出現使得我們可以在ASP.NET MVC程式裡更好的控制浏覽器請求過來的URL,不是每個請求都會響應内容,隻響應特定内容給那些有特定權限的使用者,過濾器理論上有以下功能:

判斷登入與否或使用者權限

決策輸出緩存

防盜鍊

防蜘蛛

本地化與國際化設定

實作動态Action(做權限管理系統的好東西)

先來看一個簡單的例子:建立一個AuthFiltersController,裡面有兩個Action

很顯然,第一個名為Index的Action是沒有過濾的,任何身份的請求都可以通過,隻要在浏覽器的URL欄裡鍵入:localhost:****/AuthFilters/Index 就能得到對應的視圖響應;

而第二個名為Welcome的Action上面标注了[Authorize],表示這是一個隻處理那些通過身份驗證的URL請求,如果沒有通過身份驗證就請求這個Action會被帶到登入頁面。看看配置檔案:

根據配置檔案的定義,登入頁面就是AccountController下名為LogOn的Action,那麼就建立一個AccountController,并建立兩個Action:

第一個是處理Get請求用于響應視圖頁面的,第二個是處理使用者點選送出回發的登入表單。

LogOnViewModel是使用者登入實體類,看具體定義:

ok,按F6編譯下項目,再按Ctrl + F5運作下項目,在URL裡輸入:localhost:****/AuthFilters/Index 很輕松的得到了Index這個Action的響應

ASP.NET MVC Filters 4種預設過濾器的使用【附示例】

再定位到:localhost:****/AuthFilters/Welcome

ASP.NET MVC Filters 4種預設過濾器的使用【附示例】

可見,雖然定位到了Welcome這個Action,但是卻并不像Index一樣直接傳回對應的視圖,而是被帶到了登入頁面。就是因為Welcome這個Action上被标注了[Authorize],拒絕了是以未驗證使用者的通路。

既然拒絕了未驗證的使用者,那就登入下通過驗證,看看上面LogOn裡寫的僞代碼就知道,輸入相同的使用者名和密碼就能登入成功,使用者名和密碼都輸入“wangjie”試試:

ASP.NET MVC Filters 4種預設過濾器的使用【附示例】

已經通過驗證并得到Welcome這個Action的響應了。相比之前就是多生成了一個名為“.ASPXAUTH”的Cookie,這是個預設名,配置檔案裡可以修改。同時,如果登入的時候勾選了“記住我”那麼此Cookie的過期時間就是配置檔案裡定義的2880分鐘。

ok,現在提高下難度,隻設定名為“a”、“bb”、“ccc”的使用者可以通路歡迎頁面:

再用“wangjie”登入下發現跳不到歡迎頁面了,因為指定了a、bb、ccc這三個使用者才可以登入。

先不管為何在Action上标注Users = "a,bb,ccc"就可以控制可以通路的使用者,但從操作性上來說這樣控制Action的通路權限還是很友善的。但是如果項目大,使用者對應的角色和權限變化比較大,每次變化都來重新标注Action顯然不合适。MVC架構提供的過濾器(Filters)就派上了用場:

ASP.NET MVC Filters 4種預設過濾器的使用【附示例】

上圖是Asp.Net MVC架構提供的幾種預設Filter:授權篩選器、操作篩選器、結果篩選器、異常篩選器,下面來一一講解,先看示範Demo結構圖:

ASP.NET MVC Filters 4種預設過濾器的使用【附示例】

授權篩選器用于實作IAuthorizationFilter接口和做出關于是否執行操作方法(如執行身份驗證或驗證請求的屬性)的安全決策。 AuthorizeAttribute類和RequireHttpsAttribute類是授權篩選器的示例。授權篩選器在任何其他篩選器之前運作。

建立一個繼承AuthorizeAttribute類的UserAuthorize類,F12定位到AuthorizeAttribute類,看看内部申明:

上面示範的指定使用者才可以通路就是利用了Users屬性,并由基類幫助我們驗證,隻放指定的Users使用者通過。要實作自定義的驗證隻需重寫下OnAuthorization和AuthorizeCore方法。為了示範效果,建立一個SampleData類用來初始化資料:

簡單明了,使用者擁有角色,不同角色可以通路的Action也不同。這比較符合權限項目裡的控制。再看看UserAuthorize類的具體定義:

自定義好授權類就可以到控制器上使用了,看看AuthFiltersController類:

Welcome這個Action使用了預設的授權驗證,隻要登陸成功就可以通路。其他幾個Action上都标注了自定義的UserAuthorize,并沒有标注Users="....",Roles=".....",因為這樣在Action上寫死使用者或者角色控制權限顯然是不可行的,使用者和角色的對應以及不同的角色可以操作的Action應該是從資料庫裡取出來的。為了示範就在SampleData類裡初始化了一些使用者和角色資訊,根據SampleData類的定義,很明顯wangjie擁有1号管理者角色,可以通路AuthFilters這個控制器下的所有Action,senior1、senior2擁有2号進階會員的角色,可以通路AuthFilters這個控制器下除了AdminUser之外的Action等等

再次登陸下,就發現擁有進階會員角色的使用者senior1是不可以通路AdminUser這個Action,會被帶到AuthorizationFailView屬性指定的Error視圖:

ASP.NET MVC Filters 4種預設過濾器的使用【附示例】

操作篩選器用于實作IActionFilter接口以及包裝操作方法執行。IActionFilter接口聲明兩個方法:OnActionExecuting和OnActionExecuted。OnActionExecuting在操作方法之前運作。OnActionExecuted在操作方法之後運作,可以執行其他處理,如向操作方法提供額外資料、檢查傳回值或取消執行操作方法。

結果篩選器用于實作IResultFilter接口以及包裝ActionResult對象的執行。IResultFilter接口聲明兩個方法OnResultExecuting和OnResultExecuted。OnResultExecuting在執行ActionResult對象之前運作。OnResultExecuted在結果之後運作,可以對結果執行其他處理,如修改 HTTP 響應。OutputCacheAttribute 類是結果篩選器的一個示例。

操作篩選器和結果篩選器都實作ActionFilterAttribute類,看看類裡定義的方法:

根據方法的名字就知道4個方法執行的順序了:

OnActionExecuting是Action執行前的操作、OnActionExecuted則是Action執行後的操作、OnResultExecuting是解析ActionResult前執行、OnResultExecuted是解析ActionResult後執行

即:Action執行前:OnActionExecuting方法先執行→Action執行 →OnActionExecuted方法執行→OnResultExecuting方法執行→傳回的ActionRsult中的 executeResult方法執行→OnResultExecuted執行

完全可以重寫OnActionExecuting方法實作上面授權篩選器一樣的功能,因為OnActionExecuting方法是在Action方法執行前運作的,自定義一個實作ActionFilterAttribute類的ActionFilters類,OnActionExecuting方法這麼寫:

看看如何在ActionFiltersController控制器裡使:

很明顯Index和Details這兩個Action同用一個權限,看看初始化資料SampleData類的定義:

隻有2和3号角色可以通路,那麼1号角色的wangjie使用者應該是通路不了的,登入試試:

ASP.NET MVC Filters 4種預設過濾器的使用【附示例】

異常篩選器用于實作IExceptionFilter接口,并在ASP.NET MVC管道執行期間引發了未處理的異常時執行。異常篩選器可用于執行諸如日志記錄或顯示錯誤頁之類的任務。HandleErrorAttribute類是異常篩選器的一個示例。

有之前授權篩選器、操作和結果篩選器的使用經驗,再看異常篩選器就簡單許多了,來看看自定義的繼承自HandleErrorAttribute類的異常篩選類ExceptionFilters:

看看如何在視圖中使用:

View是制定的捕獲異常後顯示給使用者的視圖:

ASP.NET MVC Filters 4種預設過濾器的使用【附示例】

再看一個Action:

把string類型的資料強轉int,肯定得報FormatException異常,看看ExceptionDetails視圖如何定義的:

浏覽器顯示結果:

ASP.NET MVC Filters 4種預設過濾器的使用【附示例】

感謝閱讀,如果覺得還不錯,請不吝給我點個“贊”,謝謝。

<a href="http://files.cnblogs.com/oppoic/zy_FiltersDemo4Blog.zip" target="_blank">本文源碼</a>

<a href="http://www.cnblogs.com/oppoic/p/ef_code_first_dbcontext.html#title03" target="_blank">系列文章導航</a>