陳剛
(內江職業技術學院 信息電子工程系,四川 內江 641100)
基于Web程序提供的產品和服務,使信息產業已滲透到人們日常生活、學習和工作的方方面面,隨之而來的是Web程序也日益成為惡意攻擊的目標。當前Web應用的開發都是基于某一軟件體系架構,與別的開發架構一樣,ASP.NET MVC的內置特征并不能對常見的網絡安全問題給予足夠的支持。為了更好地解決這個問題,同時遵循軟件工程的一些基本原則,(如分隔原則、構件原則以及復用原則等),需要配合一定的設計模式,以提高軟件產品的質量。
微軟自2009年推出ASP.NET MVC1以來,到目前為止已推出第3個正式版本,即ASP.NET MVC3。ASP.NET MVC將Web應用程序的輸入邏輯、業務邏輯和用戶界面邏輯3個不同的方面進行隔離,從而將一個MVC程序分為3個部分:模型(Model)、視圖(View)和控制器(Controller)。 每一部分都定義良好且是自包含的,即:與數據操作相關的邏輯僅包含在Model之中;與數據顯示相關的邏輯僅包含在View中;處理用戶請求和輸入僅包含在Controller中。Model、View和 Controller描述如下:
(1)Model:是對應用領域的定義,它可以是簡單的view model, 也可以是 domain model。view models只是描述在View和Controller之間傳遞的數據;而 domain model則包含業務邏輯和數據操作規則。Model的設計是MVC的核心。
(2)View:代表應用程序的用戶界面,顯示數據。
(3)Controller:是 View 和 Model之間的膠合劑,它處理請求,執行Model上定義的操作,選擇View顯示給用戶。
在處理 HTTP請求時,Controller、Model和 View之間的相互作用如圖1[1]所示。

圖1 控制器、模型和視圖之間的相互作用
ASP.NET MVC3具有非常優秀的靈活性和可擴展性,但其內置特性對基于MVC架構的應用只提供了基礎的支持,許多在實際應用中需要的功能ASP.NET MVC3并沒有實現,只是留下一些接口供開發者根據具體的應用環境加以實施。這其中比較重要的一點就是Web程序的安全性能。因為隨著信息技術的迅猛發展,人們日常的學習、生活和工作越來越依賴于Web程序所提供的服務,與此同時Web程序也日益成為惡意攻擊的目標。所以,如何在基于MVC架構的應用中解決Web程序的安全風險就成為了系統開發人員必須面對和解決的問題。據 OWASP(Open Web Application Security Project)提供的數據顯示,目前排在前兩位的Web程序安全風險是注入和 CSS(Cross-Site Scripting)[2],要較為完善地解決這個問題需要遵循軟件工程的一些基本原則,并配合使用一定的設計模式,才能開發出質量較高的應用系統。
截取過濾器模式是Web應用程序專用的,表示層的設計模式表達的是表示層的請求處理機制,它工作在應用程序級別上,對行為和信息流而非對象進行處理。截取過濾器模式的核心思想是用一個簡單的機制實現不同過濾動作的處理組件的添加和刪除,通過創建可插拔的過濾器,以標準的方式提供各種服務,而不需要修改核心的請求處理代碼。定義在這些過濾器中的方法被ASP.NET MVC的內置代碼解析出來掛接到MVC請求處理管道的恰當的位置上,并在各自的環節上截取Web請求,對請求信息進行分析、修改或重定向,從而為Web請求的處理提供諸如安全、登錄、加密等服務。
截取過濾器有如下的優點[3]:
(1)關注分離:由于過濾器中的邏輯和應用程序的邏輯是去耦合的,因此當底層特性改變時,應用程序的代碼不受影響。
(2)靈活性:由于過濾器之間是相互獨立的,因此可以任意地組合這些過濾器而不需要改變過濾器的代碼。
(3)中心化配置:由于過濾器的可組合性,可以使用單一的配置文件來加載過濾器鏈,也可以修改這個配置文件來決定處理請求的過濾器鏈的組成。
(4)可復用性:因為過濾器不依賴于它們操作的環境,因此這些過濾器能夠在別的Web程序中被重用。
(5)部署時的兼容性:由于過濾器鏈能夠在運行時基于配置文件構建出來,因此可以在部署期間改變過濾器的順序而不用修改代碼。
考慮到截取過濾器在ASP.NET WebForm架構中的實現,為保持一致性和連貫性,本文針對ASP.NET MVC3提出一種基于配置文件的全局動態截取過濾器實現方案。該方案中的任何一個全局動態過濾器是否應用于某個Controller或Action取決于該過濾器在配置文件中的配置情況,并使用庫類FilterProviders注冊過濾器。該方案簡要描述如下:
各過濾器獨立編碼,并編譯為獨立的程序集,并在配置文件中配置各過濾器要應用到哪些Controller或Action;然后,使用類 FiltersConfiguration 的 GetAllFilters()方法讀取配置文件中各個過濾器的配置信息,并用這些配置信息構建一個泛型列表List 該方案中各個部分描述如下: (1)過濾器:過濾器繼承抽象類FilterAttribute并實現接口IActionFilter、IExceptionFilter、IResultFilter、IAuthorizationFilter中的一個或多個。過濾器及其使用情況在配置文件中進行配置,配置結構如下: 其中,節點filter用于配置一個過濾器;節點element用于設置該過濾器需要應用的Controller和Action,若要應用到所有的Controller和Action,則需將該節點屬性controller和 action都設置為字符“*”;節點 Allfilters可以包含0個或多個filter節點,每個filter節點可以包含1個或多個element節點。 (2)讀取配置信息:使用自定義類 FilterNode、Element、FiltersConfiguration來讀取配置信息。FilterNode對應于filter節點,用于存放配置文件中每個過濾器的配置信息,相應地該類的成員有:屬性Name、Assembly以及Elements。Name對應于 filter節點的Name屬性,Assembly對應于 filter節點的 assembly屬性,Elements包含 filter節點所有element子節點的配置信息。Element類對應于element節點,包含屬性Controller和Action,分別對應于element節點的controller和action屬性。FiltersConfiguration類讀取配置文件中過濾器的配置信息,其方法是用GetAllFilters()實現該功能,并返回一個由過濾器配置信息構建的一個泛型列表List (3)過濾器提供器:自定義類 FilterProvider,該類實現IFilterProvider接口,用于實例化過濾器,包含有:屬性Assembly和Name、字段actions以及方法Add和GetFilters。Assembly和Name分別對應于配置文件中各過濾器的程序集名稱和類名;字段actions包含當前要實例化的過濾器在配置文件中element節點的信息,是一個ControllerAction實例的泛型列表。自定義類ControllerAction,包含屬性Controller和 Action,對應于element節點的配置信息;Add方法用于向actions字段添加element節點的信息,構建泛型列表List (4)注冊過濾器:在Global.cs文件的RegisterGlobalFilters方法中調用FiltersConfiguration的GetAllFilters方法讀取各過濾器的配置信息。針對每一個過濾器,使用一個FilterProvider實例來處理,并將其添加到MVC FilterProvider collection中。 采用了本截取過濾器實現方案的系統的應用模型如圖2所示。 圖2 本截取過濾器實現方案的應用模型 說明如下: (1)Filter1 可以是 Authorization filter或 Action filter,Filter2可以是 Action filter或 Result filter,Filter3可以是Result filter或 Exception filter。 (2)Filter1、Filter2、Filter3 中任何一個都可以代表 0個或多個過濾器。 本實例以某一在線購書網站來說明如何利用本文提出的基于ASP.NET MVC3的截取過濾器實現方案消除Web程序的注入風險 (包括SQL注入和JavaScript注入)。該系統提供常見的在線購物功能,其中的一些動態內容存在注入風險,如:注冊、會員登錄、庫存搜索、服務質量評價和書籍缺貨預訂等,由于這些風險跨越多個Controller,因此可以考慮用本文提出的截取過濾器實現方案來解決這個問題,即:針對SQL注入風險定義過濾器類 SqlInjectionFilterAttribute,針對 JavaScript注入風險定義過濾器類JavaScriptFilterAttribute。這兩個類均繼承自FilterAttribute并分別實現IActionFilter.OnActionExecuting方法和IResultFilter.OnResultExecuted方法。限于篇幅,具體的編碼不能詳述,這里僅對這兩個方法的實現算法做一扼要說明。 (1)SqlInjectionFilterAttribute.OnActionExecuting 方法 本方法對用戶輸入的內容進行過濾,以有效減少SQL注入的發生,對輸入數據中有潛在威脅的字符,如單引號、連接符、SQL關鍵字等分別進行處理:將所有單獨出現的單引號改成兩個單引號;刪除連字符;對含有諸如 exec、insert、select、delete、from、update 等 SQL 關鍵字的輸入內容,不予響應。 (2)JavaScriptFilterAttribute.OnResultExecuted 方法[4] 在本方法中對用戶輸入字符串中包含的一些特殊字符進行編碼,如:字符“<”被轉換成 <;,字符“>”轉換成 >;,字符 “&”被轉換成 &;等,從而消除JavaScript注入風險。 這兩個過濾器在Web.config中的配置如下(限于篇幅做了部分省略): 在使用ASP.NET MVC架構進行應用系統開發中有效地使用截取過濾器模式,可以使在遵循軟件工程的一些基本原則的情況下,較好地解決一些Web應用中常見的問題。本文針對ASP.NET MVC3提出一種可配的全局動態截取過濾器實現方案,并應用該方案來優化ASP.NET MVC架構的安全性能,體現了軟件工程中分隔原則、構件原則以及復用原則等一些基本準則,提高了代碼的復用性、增強了系統的靈活性,并使得程序的擴展和維護變得更加容易。 [1]FREEMAN A,SANDERSON S.Pro ASP.NET MVC3 framework[M].Apress press,2011. [2]OWASP.Category: OWASP top ten project[EB/OL]. (2012-01-18).https: //www.owasp.org/index.php/Category:OWASP_Top_Ten_Project. [3]Microsoft.Intercepting filter[EB/OL].[2012-05-01].http://msdn.microsoft.com/en-us/library/ff647251.aspx. [4]SALEM A.Intercepting filter approach to injection flaws[J].Journal of Information Processing Systems.,2010,12(4):563-574.

3 截取過濾器實現方案的應用
