Http Module 介紹
引言
Http 請求處理流程 和 Http Handler 介紹 這兩篇文章裡,我們首先了解了Http請求在伺服器端的處理流程,隨後我們知道Http請求最終會由實現了IHttpHandler介面的類進行處理(應該記得Page類實現了IHttpHandler)。從 Http 請求處理流程 一文的最後的一幅圖中可以看到,在Http請求由IHttpHandler處理之前,它需要通過一系列的Http Module;在請求處理之後,它需要再次通過一系列的Http Module,那麼這些Http Module是如何組成的?用來做什麼呢?本文將對Http Module作以介紹。
Http Module概述
暫時先不考慮我們自己實現Http Module的情況。在.Net中,Http Module 是實現了IHttpModule介面的程式集。IHttpModule 介面本身並沒有什麼好大寫特寫的,由它的名字可以看出,它不過是一個普普通通的介面而已。實際上,我們關心的是實現了這些介面的類,如果我們也編寫程式碼實現了這個介面,那麼有什麼用途。一般來說,我們可以將Asp.Net中的事件分成三個級別,最頂層是 應用程式級事件、其次是頁面級事件、最下面是控制元件級事件,事件的觸發分別與 應用程式週期、頁面週期、控制元件週期緊密相關。而 Http Module 的作用是與應用程式事件 密切相關的。
我們通過Http Module在Http請求管道(Pipeline)中註冊期望對應用程式事件做出反應的方法,在相應的事件觸發的時候(比如說BeginRequest事件,它在應用程式收到一個Http請求並即將對其進行處理時觸發),便會呼叫Http Module註冊了的方法,實際的工作在這些方法中執行。.Net 本身已經有很多的Http Module,其中包括 表單驗證Module(FormsAuthenticationModule), Session 狀態Module(SessionStateModule),輸出快取Module (OutputCacheModule)等。
註冊 Http Module
在註冊我們自己編寫的 Http Module 之前,先來看看Asp.Net中已經有的HttpModule。與 Http Handler類似,我們需要開啟機器上C:/WINDOWS/Microsoft.NET/Framework/ v2.0.50727/CONFIG 目錄下的 web.config 檔案。找到 <httpModules/> 結點,應該可以看到下面的內容:
<httpModules>
<add name="OutputCache" type="System.Web.Caching.OutputCacheModule" />
<add name="Session" type="System.Web.SessionState.SessionStateModule" />
<add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule" />
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
<add name="PassportAuthentication" type="System.Web.Security.PassportAuthenticationModule" />
<add name="RoleManager" type="System.Web.Security.RoleManagerModule" />
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
... 略
</httpModules>
我們先從結點上看,type屬性與上一節所說的http handler結點的type屬性類似,都代表了相應的程式集。但是,與http handler 不同,module只提供了一個name屬性,沒有諸如 path這樣指定某一特定(或者用萬用字元 * 代表某一種類)檔案的處理程式。這是與Module的特點相關的,我們知道 module 是響應應用程式週期中觸發的事件,對於所有提交到aspnet_isapi.dll的請求都一樣,即便請求只是像類似http://www.tracefact.net/images/logo.gif 這樣獲取一張圖片而已(對ISAPI進行過設定以後,預設aspnet_isapi.dll不接手圖片檔案)。
與Http handler類似,在這冊我們自己的http module 時,假設類名為ModuleDemo,位於myNameSpace名稱空間下,程式集名稱為myDll,我們只需將myDll.dll拷貝到Bin目錄下,並在站點的 web.config 檔案 system.web 結點下建立 httpModules 結點:
<system.web>
<httpModules>
<add name="CustomModuleName" type="myNameSpace.ModuleDemo, myDll"/>
</httpModules>
</system.web>
type屬性由分號“,”分為兩部分,前面是名稱空間及類名,也就是型別名;後面是程式集名。如果我們將程式碼建立在App_Code目錄中,則不需要再指定程式集名。
name屬性由我們自己命名,不一定與類名相同,此處我將它命名為“CustomModuleName”。我們可以通過應用程式(HttpApplication)的Modules屬性獲取HttpModuleCollection集合,然後通過name屬性,進一步獲取HttpModule物件。
通過name屬性,我們還可以在global.asax中檔案中編寫自定義HttpModule暴露出的事件的處理程式,它採用的格式是:void ModuleName_EventName(object sender, EventArgs e)。我們將在後面做更詳細介紹。
Asp.Net 內建的 Http Modules
下面這張表格列出了C:/WINDOWS/Microsoft.NET/Framework/ v2.0.50727/CONFIG下的Web.Config中的 Asp.Net 內建的Http Modules 及其主要作用。
名稱 | 型別 | 功能 |
OutputCache | System.Web.Caching.OutputCacheModule | 頁面級輸出快取 |
Session | System.Web.SessionState.SessionStateModule | Session狀態管理 |
WindowsAuthentication | System.Web.Security.WindowsAuthenticationModule | 用整合Windows身份驗證進行客戶端驗證 |
FormsAuthentication | System.Web.Security.FormsAuthenticationModule | 用基於Cookie的窗體身份驗證進行客戶端身份驗證 |
PassportAuthentication | System.Web.Security.PassportAuthenticationModule | 用MS護照進行客戶身份驗證 |
RoleManager | System.Web.Security.RoleManagerModule | 管理當前使用者角色 |
UrlAuthorization | System.Web.Security.UrlAuthorizationModule | 判斷使用者是否被授權訪問某一URL |
FileAuthorization | System.Web.Security.FileAuthorizationModule | 判斷使用者是否被授權訪問某一資源 |
AnonymousIdentification | System.Web.Security.AnonymousIdentificationModule | 管理Asp.Net應用程式中的匿名訪問 |
Profile | System.Web.Profile.ProfileModule | 管理使用者檔案檔案的創立 及相關事件 |
ErrorHandlerModule | System.Web.Mobile.ErrorHandlerModule | 捕捉異常,格式化錯誤提示字元,傳遞給客戶端程式 |
我們將在後面用程式設計的方式來檢視它。
IHttpModule介面
看了這麼多理論知識,本節將開始動手寫點程式,實現自己的Http Module。我們首先需要看下IHttpModule 介面,它包括下面兩個方法:
public void Init(HttpApplication context);
public void Dispose();
Init():這個方法接受一個HttpApplication物件,HttpApplication代表了當前的應用程式,我們需要在這個方法內註冊 HttpApplication物件暴露給客戶端的事件。可見,這個方法僅僅是用來對事件進行註冊,而實際的事件處理程式,需要我們另外寫方法。
整個過程很好理解:
- 當站點第一個資源被訪問的時候,Asp.Net會建立HttpApplication類的例項,它代表著站點應用程式,同時會建立所有在Web.Config中註冊過的Module例項。
- 在建立Module例項的時候會呼叫Module的Init()方法。
- 在Init()方法內,對想要作出響應的HttpApplication暴露出的事件進行註冊。(僅僅進行方法的簡單註冊,實際的方法需要另寫)。
- HttpApplication在其應用程式週期中觸發各類事件。
- 觸發事件的時候呼叫Module在其Init()方法中註冊過的方法。
NOTE:如果你不瞭解事件註冊等相關內容,請參閱 C#中的委託與事件 一文。
Dispose():它可以在進行垃圾回收之前進行一些清理工作。
綜上所述:實現一個 IHttpModule 的模板一般是這樣的:
public class ModuleDemo:IHttpModule
{
public void Init(HttpApplication context) {
// 註冊HttpApplication應用程式 BeginRequest 事件
// 也可以是其他任何HttpApplication暴露出的事件
context.BeginRequest += new EventHandler(context_BeginRequest);
}
void context_BeginRequest(object sender, EventArgs e) {
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
// 做些實際的工作,HttpContext物件都獲得了,剩下的基本可以自由發揮了
}
public void Dispose() {
}
}
通過Http Module向Http請求輸出流中寫入文字
本例中,我們僅用BeginRequest事件和 EndRequest 事件對 Http Module 的使用作以說明。我們通過這個範例,瞭解 Http Module 基本的使用方法。
首先,請建立一個新的站點,在App_Code目錄中新增類檔案: ModuleDemo.cs:
public class ModuleDemo:IHttpModule
{
// Init方法僅用於給期望的事件註冊方法
public void Init(HttpApplication context) {
context.BeginRequest += new EventHandler(context_BeginRequest);
context.EndRequest += new EventHandler(context_EndRequest);
}
// 處理BeginRequest 事件的實際程式碼
void context_BeginRequest(object sender, EventArgs e) {
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
context.Response.Write("<h1 style='color:#00f'>來自HttpModule 的處理,請求到達</h1><hr>");
}
// 處理EndRequest 事件的實際程式碼
void context_EndRequest(object sender, EventArgs e) {
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
context.Response.Write("<hr><h1 style='color:#f00'>來自HttpModule的處理,請求結束</h1>");
}
public void Dispose() {
}
}
上面的程式碼很簡單,它註冊了 HttpApplication例項的 BeginRequest 事件 和 EndRequest事件,事件處理方法的作用僅僅是在http請求開始和結束的時候,給http請求的輸入流中分別寫入不同的內容。
接下來在 Web.config 的 System.web 結點中寫入以下內容:
<system.web>
<httpModules>
<add name="MyModule" type="ModuleDemo" />
</httpModules>
</system.web>
然後,開啟建立站點時自動建立的 Default.aspx檔案,在裡面打幾個字,為了做區分,我輸入的是:位於.aspx頁面上的文字。然後,我們在瀏覽器中開啟它,應該會看到像這樣:
然後我們再新建一個 Default2.aspx,在瀏覽器中瀏覽,可以看到,兩個頁面的效果相同。這說明對於不同的兩個檔案,http Module都起了作用,可見它確實是位於應用程式級,而非頁面級。
現在,我們再開啟站點中的一張圖片檔案,發現顯示出的是一個紅叉叉,為什呢?因為Http Module 針對是http 請求,而不是某個或某一類檔案,所以當請求一張圖片的時候,我們編寫的http Module依然會起作用,將文字插入到二進位制圖片中,破壞了檔案格式,自然只能顯示紅叉叉了。
NOTE:如果你發現你的圖片顯示正常,請不要驚訝,事情是這樣的:回想一下第一節我們討論到的,對於圖片檔案,由IIS直接處理,並不會交由aspnet_isapi.dll,所以,Module無法捕獲對於圖片型別檔案的請求。解決方法就是在IIS中進行設定一下。
這裡需要提請注意的是:如果你使用Vs2005自帶的Local Server,那麼你無需對IIS進行設定,所有的不論圖片還是任何檔案型別,都會交由aspnet_isapi.dll處理。
遍歷Http Module集合
現在,我們通過遍歷 HttpModuleCollection 集合來檢視註冊給應用程式的所有 Http Module 的名稱。
新建一個檔案 RegisteredModules.aspx,在程式碼後置檔案中新增如下方法:
private string ShowModules() {
HttpApplication app = Context.ApplicationInstance; //獲取當前上下文的HttpApplication環境
HttpModuleCollection moduleCollection = app.Modules; //獲取所有Module集合
// 獲取所有的 Module 名稱
string[] moduleNames = moduleCollection.AllKeys;
System.Text.StringBuilder results = new System.Text.StringBuilder(); //遍歷結果集
foreach (string name in moduleNames) {
// 獲得Module名稱
results.Append("<b style='color:#800800'>名稱:" + name + "</b><br />");
// 獲得Module型別
results.Append("型別:" + moduleCollection[name].ToString() + "<br />");
}
return results.ToString();
}
然後在Page_Load方法中輸出一下:
protected void Page_Load(object sender, EventArgs e)
{
Response.Write(ShowModules());
}
我們應該可以看到下面這樣的畫面:
與之前列出的那張表格比較一下,可以看出是幾乎完全一致的(多了一個DefaultAuthentication)。另外注意上圖的倒數第四行,那不是我們自己定義的Module麼?name為MyModule,型別為ModuleDemo。
Global.asax檔案與 Http Module
早在asp時代,大家就知道這個檔案了。它主要用於放置對於 應用程式事件或者 Session事件的響應程式。大家熟悉的有Application_Start、Application_End、Session_Start、Session_End 等。
在asp.net中,Glabal不僅可以註冊應用程式和Session事件,還可以註冊Http Module暴露出的事件;不僅可以註冊系統Module的事件,也可以註冊我們自己義的Module暴露出的事件。在具體介紹之前,這裡需要首先注意兩點:
- 在每處理一個Http請求時,應用程式事件都會觸發一遍,但是Application_Start和 Application_End 例外,它僅在第一個資原始檔被訪問時被觸發。
- Http Module無法註冊和響應Session事件,對於Session_Start 和 Session_End,只能通過Glabal.asax來處理。
好了,我們現在修改之前 ModuleDemo 範例程式,給它像下面這樣給它新增一個事件(為了使程式簡潔一些,我做了簡化):
public class ModuleDemo : IHttpModule {
// 宣告一個事件
public event EventHandler ExposedEvent;
// Init方法僅用於給期望的事件註冊方法
public void Init(HttpApplication context) {
context.BeginRequest += new EventHandler(context_BeginRequest);
}
// 處理BeginRequest 事件的實際程式碼
void context_BeginRequest(object sender, EventArgs e) {
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
context.Response.Write("<h3 style='color:#00f'>來自HttpModule的處理,請求到達</h3><hr>");
OnExposedEvent(new EventArgs()); // 呼叫方法
}
protected override void OnExposedEvent(EventArgs e) {
if (ExposedEvent != null) // 如果Global中有註冊
ExposedEvent(this, e); // 呼叫註冊了的方法
}
public void Dispose() {
}
}
接下來,我們在站點中建立一個 Global.asax 檔案,在裡面新增如下程式碼,注意到格式是:void 模組名_事件名(object sender, EventArgs e)。
void MyModule_ExposedEvent(object sender, EventArgs e)
{
Response.Write("<h3 style='color:#800800'>來自 Global.asax 的文字</h2>");
}
現在,我們開啟之前的頁面,應該可以見到這樣,可見,我們成功的將 Glabal.asax檔案與我們自己定義的Http Module所暴露出的事件 ExposedEvent 聯絡到了一起:
總結
本文簡單地介紹了什麼是Http Module。我們首先了解了Http Module的作用,然後查看了Asp.Net 內建的Module,接著我們介紹了IHttpModule介面,並通過了一個簡單的範例實現了此介面,最後我們討論了 Http Module與 Global.asax 檔案的聯絡。
本文僅僅是對IHttpModule作以簡單介紹,對其更多的實際應用,會在後續文章中補充。
相關推薦
Http Module 介紹
引言 Http 請求處理流程 和 Http Handler 介紹 這兩篇文章裡,我們首先了解了Http請求在伺服器端的處理流程,隨後我們知道Http請求最終會由實現了IHttpHandler介面的類進行處理(應該記得Page類實現了IHttpHandler)。從 Http 請
HTTP 之 HTTP概念介紹
http 協議 術語 工作機制1 概述本文將對HTTP協議的發展,相關術語,工作機制進行介紹2 HTTP協議發展介紹.http/0.9:1991,原型版本,功能簡陋,只有一個命令GETGET /index.html ,服務器只能回應HTML格式字符串,不能回應別的格式.http/1.0: 1996年5月,
Linux nginx-http配置介紹
Linux nginxnginx工作流程圖 http部分工作流程大致如一個master開啟多個worker,網絡io一般用epoll實現當個worker的高並發,文件io用sendfile,aio等高效移步io,實現一個http請求響應。io部分請參考:http://blog.51cto.com/marvin
SQL註入(HTTP頭介紹)
unix 連接 代理服務器 connect 詳解 mysql 等待 .com max-age HTTP 頭部詳解(轉自網絡)1、 Accept:告訴 WEB 服務器自己接受什麽介質類型,*/* 表示任何類型,type/* 表示該類型下的所有子類型,type/sub-type
Go 1.11 Module 介紹
自己 vendor ext tle gopath get 根目錄 pkg 三方 title: "Go 1.11 Module" date: 2018-10-26T23:50:56+08:00 draft: false --- Go 1.11 Modul
HTTP服務介紹
摘自 https://mp.weixin.qq.com/s?__biz=MzI4NDM5NzE4Ng==&mid=2247484093&idx=1&sn=3d87e9772ffb3c9b0d40f7898970f4da&chksm=ebfd5950dc8ad046bd609e
【翻譯】OpenTSDB 2.3 文件--HTTP API介紹
HTTP API OpenTSDB提供基於HTTP的應用程式程式設計介面,以實現與外部系統的整合。幾乎所有OpenTSDB功能都可通過API訪問,例如查詢時間序列資料,管理元資料和儲存資料點。在研究各資料點資訊之前,請閱讀整個頁面以獲取有關標準API行為的重要資訊。 概覽 HTT
JAVA 基礎 HTTP的介紹
plain input 服務器 組件 oid req target tip web服務 目錄 http的方法 http請求頭Content-Type編碼指定 form表單 httpClient的使用(圖片來自於網絡) http的方法 OPTIOINS
HTTP協議介紹(POST、GET、Content-Type)
什麼是HTTP? 超文字傳輸協議(HyperText Transfer Protocol -- HTTP)是一個設計來使客戶端和伺服器順利進行通訊的協議。 HTTP/1.1 協議規定的 HTTP 請求方法有 OPTIONS、GET、HEAD、POST、PUT、DELETE
OkHttp的基本使用-1(Http協議介紹)
Http是一個屬於應用層的面向物件的協議,由於其簡潔、快速的方式,適用於分散式超媒體資訊系統。 它於1990年提出,經過今年的使用與發展,得到不斷地完善和擴充套件。目前在WWW中使用的是HTTP/1.
okHttp各個module介紹
上一篇我們簡單介紹了okHttp,瞭解了OkHttp的基本用法,並下載了okhttp的原始碼。本篇我們將一起來看看okhttp原始碼的目錄結構,來大概瞭解下okHttp原始碼下的各個module的作用。 okHttp的構建工具使用的是maven,關於mav
C socket 傳送HTTP簡單介紹
HTTP請求頭部樣例: GET http://www.baidu.com/ HTTP/1.1 Accept: html/text Host: 220.181.6.175:80 Connection: Close 這是一個請求百度頁面的頭部。 屬性和值的命名中間用:和空格隔
Http頭介紹:Expires,Cache-Control,Last-Modified,ETag
快取對於web開發有重要作用,尤其是大負荷web系統開發中。 快取分很多種:伺服器快取,第三方快取,瀏覽器快取等。其中瀏覽器快取是代價最小的,因為瀏覽器快取依賴的是客戶 端,而幾乎不耗費伺服器端的資源。 讓瀏覽器做快取需要給瀏覽器傳送指定的Http頭,告訴瀏覽器快取多
android-async-http AsyncHttpClient介紹和使用
轉自http://www.cnblogs.com/xiaoweiz/p/3916790.html 及http://blog.csdn.net/redarmy_chen/article/details/26976463 android-async-http 是針對Androi
【C#.NET】Http Handler 介紹
Http Handler 介紹 引言 在 Part.1 Http請求處理流程 一文中,我們瞭解了Http請求的處理過程以及其它一些運作原理。我們知道Http管道中有兩個可用介面,一個是IHttpHandler,一個是IHttpModule,但在Part.1中,我並沒
HTTP報文介紹
HTTP報文分為HTTP/1.0和HTTP/1.1。HTTP/1.0是使用最為廣泛的HTTP版本,他在HTTP/0.9的基礎上添加了HTTP請求頭,支援了更多的請求的方法,並能對多媒體物件進行處理。HTTP/1.0規定瀏覽器與伺服器只保持短暫的連線,瀏覽器的每次與伺服器簡歷
HTTP協議介紹
一.HTTP介紹 HTTP:超文字傳輸協議,是Web聯網的基礎 作用:從伺服器傳輸html到本地瀏覽器的傳輸協議 版本:HTTP 0.9/1.0/1.1 特點:無狀態,無連線,基於TCP 二.
Http Handler 介紹 httpHandler 驗證碼 圖片防盜鏈
Http Handler 介紹 引言 在 Part.1 Http請求處理流程 一文中,我們瞭解了Http請求的處理過程以及其它一些運作原理。我們知道Http管道中有兩個可用介面,一個是IHttpHandler,一個是IHttpModule,但在Part.1中,我並沒有詳細講述如何對它們進行程式設計,只是輕
libcurl庫的http部分介紹
//採用CURLOPT_RESUME_FROM_LARGE 實現檔案斷點續傳功能 #include <stdlib.h> #include <stdio.h> #include <sys/stat.h> #include <curl/curl.h> //這個
HTTP通俗介紹
其它 通知 瀏覽器 enter鍵 都是 別人 情況下 完成 好的 今天來介紹一下,HTTP是什麽。 介紹這個概念之前,我們先來介紹一下什麽是規範,或規則。這裏我們舉個例子,交通規則。試想如果馬路上沒有交通規則,那麽交通擁堵的情況下,車輛和行人就不知道什麽時候自己該行走,那個