1. 程式人生 > >ASP.NET沒有魔法——ASP.NET MVC 過濾器(Filter)

ASP.NET沒有魔法——ASP.NET MVC 過濾器(Filter)

上一篇文章介紹了使用Authorize特性實現了ASP.NET MVC中針對Controller或者Action的授權功能,實際上這個特性是MVC功能的一部分,被稱為過濾器(Filter),它是一種面向切面程式設計(AOP)的實現,本章將從以下幾個方面來介紹ASP.NET MVC中的過濾器。

  ● ASP.NET MVC 中的過濾器及其型別
  ● ASP.NET MVC 中常用的過濾器
  ● ASP.NET MVC 過濾器的應用方法
  ● ASP.NET MVC Action方法的呼叫與Filter的執行
  ● ASP.NET MVC 過濾器的建立與獲取
  ● ASP.NET MVC Action及Result過濾器的管道執行

ASP.NET MVC中的過濾器及其型別

  在之前的Entity Framework文章中介紹了EF自帶的攔截器(interceptors)功能,ASP.NET MVC中的過濾器也和攔截器一樣是一種面向切面(AOP)的程式設計方式,是一種不修改原始碼的前提下對應用程式進行拓展的程式設計方式。一般AOP用來處理日誌記錄、效能統計、安全控制、事務處理、異常處理等不會對原有業務資料進行修改的功能。
  ASP.NET MVC中把過濾器分為以下幾類,每一類都是通過一個對應的介面定義的:
  ● 身份驗證過濾器(IAuthenticationFilter):這個過濾器是在MVC5中加入的,它是所有過濾器中優先順序最高的,使用身份驗證過濾器可以為Action、Controller或者所有的Controller新增身份驗證邏輯。身份驗證過濾器的核心在於根據請求資訊建立一個Principal物件

(注:使用Identity的身份驗證功能實際上也是建立一個Principal物件),以下是IAuthenticationFilter的定義:

  

  其中身份驗證上下文有一個IPrincipal的屬性:

  

  ● 授權過濾器(IAuthorizationFilter):授權過濾器用來處理Controller以及Action的訪問限制。
  ● Action方法過濾器(IActionFilter):Action過濾器可用於在Action方法執行前和執行後新增邏輯。
  ● 結果過濾器(IResultFilter):結果過濾器可以在結果執行前和執行後新增邏輯。(注:ASP.NET MVC中的Action返回結果為ActionResult型別,該抽象型別定義了一個執行方法ExecuteResult,結果的執行實際上是對返回結果的處理)

  

  比如FileResult的執行實際上是在Http響應頭中添加了適當的引數然後將檔案的二進位制資料寫到了響應體中,相當於檔案的下載功能。

  

  更多結果執行內容會在後續文章中介紹。

  ● 異常過濾器(IExceptionFilter):異常過濾器就是Action方法在執行的過程中丟擲異常時,用來新增異常處理邏輯的過濾器。

ASP.NET MVC 中常用的過濾器

  上面介紹了過濾器的類別,現在介紹一下每一個類別下常用的過濾器有哪些:
  ● 身份驗證過濾器(IAuthenticationFilter):由於身份驗證過程可以使用Identity等成熟元件來完成,所以身份驗證過濾器暫時沒有找到適合的可以用的過濾器。如果系統有需求可自定義。
  ● 授權過濾器(IAuthorizationFilter):
    ○ Authorize:基於使用者名稱、角色的使用者授權。
    ○ RequireHttps:基於Https的訪問授權。
    ○ ValidateInput:ASP.NET MVC在執行前會驗證請求資訊中是否包含HTML等不合法資訊以避免XSS攻擊,但是有的時候需求就是要提交HTML資料,在提交這些資料時可以使用該過濾器將EnableValidation設為false,MVC將跳過資料驗證。
    ○ ValidateAntiForgeryToken:該過濾器可以對HtmlHelper的AntiForgeryToken方法生成防偽令牌進行校驗,以避免CSRF跨站偽造攻擊。
  ● Action過濾器(IActionFilter):一般根據需求自定義實現。
  ● 異常過濾器(IExceptionFilter):
    ○ HandleError:用於處理Action方法丟擲的異常(預設的MVC模板會新增一個全域性HandleError過濾器)。

  另外還需要注意的是ASP.NET MVC中的Controller實際上也是一個過濾器,因為Controller基類實現了所有過濾器介面:

  

  所以如果某一Controller中有特殊的處理需求,無需定義過濾器,在Controller中實現過載對應過濾器的方法即可:

  

ASP.NET MVC 過濾器的應用方法 

  ASP.NET MVC中的過濾器可以通過以下幾種方法使用:
  1. 通過特性的方式在Controller以及Action上標記使用,但是要注意的是以特性方式使用的過濾器除了實現對應的過濾器介面外還需要將其封裝為一個.Net特性並實現IMvcFilter介面,最為方便的是直接繼承FilterAttribute型別實現,如:

  

  2. 通過全域性過濾器表新增過濾器,這樣新增的過濾器會對所有Controller的Action方法生效。

  

  3. 在Controller型別中通過過載對應過濾器方法的方式實現,上面說明了Controller本身就是一個實現了所有過濾器的型別。

ASP.NET MVC Action方法的呼叫與Filter的執行

  過濾器是在Action方法執行的過程中呼叫執行的,所以首先要了解Action的執行過程,在之前的文章中介紹了Controller的建立與執行《ASP.NET沒有魔法——ASP.NET MVC Controller的例項化與執行》,而這裡就基於該文章,來對Action的執行過程進行介紹,Controller的執行是通過Controller型別的ExecuteCore方法完成的:

  

  而從程式碼中也可以看到Controller的執行實際上是通過ActionInvoker根據Action的名稱來呼叫Action方法的執行,在ASP.NET MVC中預設使用一個名為 AsyncControllerActionInvoker的非同步Action呼叫器:

  

  它除了非同步功能外還繼承了同步的ControllerActionInvoker型別,非同步主要是為了提高請求處理的吞吐量,這裡將使用同步版本的程式碼進行Action與Filter執行介紹。

  ControllerActionInvoker:

   

  從程式碼定義中可以看出以下幾點:
  1. 它的核心方法是InvokeAction,它處理了所有的過濾器、Action方法的呼叫處理邏輯。
  2. GetFilters方法,它用於獲取所有相關的過濾器。
  3. InvokeActionMethodWithFilters、InvokActionResultWitherFilters、InvokeAuthenticationFilters、InvokeAuthenticationFiltersChallenge、InvokeAuthorizationFilters、InvokeExceptionFilters等相關方法就是用來呼叫對應型別的過濾器執行的方法。
  這裡通過原始碼分析的方式來介紹過濾器在ActionInvoker的執行過程:

 View Code

  通過對上面程式碼的分析得出以下幾個結論:
  1. 通過Controller上下文及Action的資訊找到真實的Action方法後,獲取所有過濾器。
  2. 先執行身份驗證過濾器。
  3. 通過身份驗證過濾器後執行授權過濾器。
  4. 授權過濾器通過後,執行Action過濾器及Action方法。
  5. 執行Result過濾器及Result。

ASP.NET MVC 過濾器的建立與獲取

  根據上面的介紹知道了可以通過全域性過濾器、特性標記以及過載Controller過濾器方法這三種方式來應用過濾器的,那麼在執行過程中是如何通過ActionInvoker的GetFilters方法建立和獲取它們的呢?
  ● 過濾器提供器(FilterProvider):ASP.NET MVC中有一個過濾器提供器的概念和實際物件,它有三種實現分別對應上述的三種應用方式:
    ○ GlobalFilterCollection:用於儲存全域性過濾器例項,可以直接通過它新增和獲取過濾器例項,通過它建立的過濾器的Scope為Gobal,建立時可以通過Order引數來決定全域性過濾器的執行順序:

  

    ○ FilterAttributeFilterProvider:過濾器特性提供器,通過查詢Controller以及Action上的特性來建立過濾器,根據特性標記位置將Scope分為Controller以及Action,在應用特性時可以設定特性的Order屬性來決定過濾器的執行順序:

    

    ○ ControllerInstanceFilterProvider:控制器例項過濾器提供器,它用於獲取當前Controller例項的過濾器,並且過濾器的Scope為First:

    

  ● 過濾器提供器集合(FilterProviderCollection):它包含了上述的所有過濾器提供器,ActionInvoker就是通過它來獲取所有相關過濾器的:

  

  FitlerProviderCollection獲取過濾器時通過以上三種提供器獲取所有相關的過濾器並根據Scope以及Order對過濾器進行排序,以決定過濾器執行順序。

ASP.NET MVC Action及Result過濾器的管道執行

  在Action和Result過濾器的定義中都有兩個方法,分別是OnXXXExecuting以及OnXXXExecuted,它們對應Action或者Reuslt執行前和執行後。當一個Action上存在多個Action或者Result過濾器時就會形成一個過濾器管道,其執行方式如下圖所示:

  

小結

  本文除了介紹ASP.NET MVC的過濾器功能及常用的過濾器外,還通過程式碼的形式分析了它建立與執行的過程。在一般的專案中使用ASP.NET MVC自帶的過濾器就可以滿足需求,如授權、錯誤處理等,但過濾器作為ASP.NET MVC中的一種重要的AOP拓展方式,合理的運用過濾器可以實現,如日誌記錄、效能分析、Action的事務執行(http://blog.gauffin.org/2012/06/how-to-handle-transactions-in-asp-net-mvc3/,這篇文章就利用Action過濾器實現了資料庫的事務)等等功能,並且可以靈活的在不影響原有程式碼邏輯的情況下對系統進行拓展。

相關推薦

ASP.NET沒有魔法——ASP.NET MVC 過濾器(Filter)

上一篇文章介紹了使用Authorize特性實現了ASP.NET MVC中針對Controller或者Action的授權功能,實際上這個特性是MVC功能的一部分,被稱為過濾器(Filter),它是一種面向切面程式設計(AOP)的實現,本章將從以下幾個方面來介紹ASP.NET

ASP.NET沒有魔法——ASP.NET MVC 與數據庫之ORM

設計器 不同類 使用 運行程序 relation 編譯 如何 n) and 什麽是ORM   對象關系映射(Object Relational Mapping,簡稱ORM,或O/RM,或O/R mapping),是一種程序技術,用於實現面向對象編程語言裏不同類型系統的數據

ASP.NET沒有魔法——ASP.NET MVC 與數據庫之EntityFramework配置與連接字符串

client frame view 必須 多個數據庫 epo get base fault   前幾篇文章中介紹了如何使用Entity Framework來操作數據庫,但是對EF的配置、連接字符串的指定仍然存在一些疑問。  本章將對EF的配置進行介紹。  EF可以通過兩種方

ASP.NET沒有魔法——ASP.NET MVC 與數據庫之MySQL&EF

dll 程序 connector resolv rdquo ram key log 找到   本章將介紹如何通過Entity Framework來使用My SQL,之前介紹EF時介紹了provider這個配置項,而且也介紹了在ASP.NET訪問MySQL數據仍然是通過ADO

ASP.NET沒有魔法——ASP.NET MVC 與數據庫之EF實體類與數據庫結構

類之間的關系 context 模型 rst 例子 style 方法 eid 一個   大家都知道在關系型數據庫中每張表的每個字段都會有自己的屬性,如:數據類型、長度、是否為空、主外鍵、索引以及表與表之間的關系。但對於C#編寫的類來說,它的屬性只有一個數據類型和類與類之間的關

ASP.NET沒有魔法——ASP.NET MVC路由

文件相對路徑 register 以及 out insert 技術分享 順序 reg 沒有   之前的文章中介紹了My Blog文章維護功能的開發,開發過程中使用Area的方法建立了用於維護文章的Controller、View和Model。但是無論代碼怎麽變對於瀏覽器來說都是

ASP.NET沒有魔法——ASP.NET MVC使用Oauth2.0實現身份驗證

重定向 adt imp img imsi als jwt and -i 原文:ASP.NET沒有魔法——ASP.NET MVC使用Oauth2.0實現身份驗證  隨著軟件的不斷發展,出現了更多的身份驗證使用場景,除了典型的服務器與客戶端之間的身份驗證外還有,如服務與服務之間

ASP.NET沒有魔法——ASP.NET OAuth、jwt、OpenID Connect

ims -c ive which 彌補 ons 編寫 速度 種類 原文:ASP.NET沒有魔法——ASP.NET OAuth、jwt、OpenID Connect  上一篇文章介紹了OAuth2.0以及如何使用.Net來實現基於OAuth的身份驗證,本文是對上一篇文章的補充

ASP.NET沒有魔法——Identity與Owin

註冊方法 委托 地址 結構 錯誤提示 請求 ger 特殊 設計   上篇文章介紹了如何在ASP.NET MVC項目中引入Identity組件來實現用戶註冊、登錄及身份驗證功能,並且也提到了Identity是集成到Owin中的,本章就來介紹一下什麽是Owin以及如何使用Ow

Asp.Net MVC3 簡單入門詳解過濾器Filter

添加 重復 權限 組件 再次 ace text ext 開發 前言 在開發大項目的時候總會有相關的AOP面向切面編程的組件,而MVC(特指:Asp.Net MVC,以下皆同)項目中不想讓MVC開發人員去關心和寫類似身份驗證,日誌,異常,行為截取等這部分重復的代碼,那我們可以

.NET魔法 - asp.net core 配置檔案的"物件儲存"

來,全都是乾貨。 我們都知道在Framework版本的mvc專案中,配置資料是通過web.config裡的appSettings節點配置,我們不得不寫一些讀取配置檔案字串的類,比如儲存在靜態的變數中。 而在mvc core中,這種不優雅的讀取字串的方式得到了進化,以json資料寫入和讀取的方式很優雅,省了很

.NET魔法 - asp.net core 日誌系統

asp.net core 裡如何記錄日誌呢? 這要從asp.net core的依賴注入說起,在asp.net core裡的依賴注入真是無所不在,各種面向切面的介面與事件。 好吧,來點乾貨。 首先,我們希望有這樣一種呼叫方式(或者說asp.net core整合的日誌功能只能用這種方式): 在asp.

Asp.Net MVC3 簡單入門詳解過濾器Filter(身份驗證、快取、防盜鏈、國際化等)

下面我們說幾個系統的Filter三、AcceptVerbs規定頁面的訪問形式,如 [AcceptVerbs(HttpVerbs.Post)]public ActionResult Example(){return View(); }頁面只能以Post形式訪問,即表單提交。四、Ac

ASP.NET MVCFilter過濾器的使用

MVC Filter是典型的AOP(面向切面程式設計)應用,在ASP.NET MVC中的4個過濾器型別,如下: 過濾器型別 介面 預設實現 描述 Action IActionFilter

ASP.NET MVC 過濾器(三)

 ASP.NET MVC 過濾器(三) 前言 本篇解說行為過濾器的執行過程,過濾器實現、使用方式有AOP的意思。能夠通過學習瞭解過濾器在框架中的執行過程從而獲得一些AOP方面的知識(在順序執行的過程中,這樣的程式設計模式就是橫向的插入點),言歸正傳,我們還是以學習過濾

ASP.NET MVC 重點教程一週年版 第六回 過濾器Filter

在Asp.netMvc中當你有以下及類似以下需求時你可以使用Filter功能 判斷登入與否或使用者許可權 決策輸出快取 防盜鏈 防蜘蛛 本地化與國際化設定  實現動態Action Filter是一種宣告式程式設計方式,在Asp.net MVC中它只能限制於Action(或它的Con

16、ASP.NET MVC入門到精通——MVC過濾器

在ASP.NET MVC中有四種過濾器型別  Action 1、在ASP.NET MVC專案中,新建資料夾Filter,然後新建類MyCustormFilter,繼承自ActionFilterAttribute類,我們來看下ActionFilterAttribute類有如下四個方法,從命名我應該就

ASP.NET Core MVC 過濾器介紹

過濾器的作用是在 Action 方法執行前或執行後做一些加工處理。使用過濾器可以避免Action方法的重複程式碼,例如,您可以使用異常過濾器合併異常處理的程式碼。 過濾器如何工作? 過濾器在 MVC Action 呼叫管道中執行,有時稱為過濾器管道。MVC選擇要執行的Ac

關於ASP.NET WebForm與ASP.NET MVC的比較

WebForm的理解 1、 WebForm概念 ASP.NETWebform提供了一個類似於Winform的事件響應GUI模型(event-drivenGUI),隱藏了HTTP、HTML、JavaScript等細節,將使用者介面構建成一個伺服器端的樹結構控制元件(Co

ASP.NET MVC Action Filter

快取在開發高擴充性WEB程式的時候扮演著很重要的角色.我們可以將HTTP請求在一個定義的時間內快取在使用者的瀏覽器中,如果使用者在定義的時間內請求同一個URL,那麼使用者的請求將會從使用者瀏覽器的快取中載入,而不是從伺服器.你可以在ASP.NET MVC應用程式中使用下面的Action Filter來