1. 程式人生 > >Http Module 介紹

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物件暴露給客戶端的事件。可見,這個方法僅僅是用來對事件進行註冊,而實際的事件處理程式,需要我們另外寫方法。

整個過程很好理解:

  1. 當站點第一個資源被訪問的時候,Asp.Net會建立HttpApplication類的例項,它代表著站點應用程式,同時會建立所有在Web.Config中註冊過的Module例項。
  2. 在建立Module例項的時候會呼叫Module的Init()方法。
  3. 在Init()方法內,對想要作出響應的HttpApplication暴露出的事件進行註冊。(僅僅進行方法的簡單註冊,實際的方法需要另寫)。
  4. HttpApplication在其應用程式週期中觸發各類事件。
  5. 觸發事件的時候呼叫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暴露出的事件。在具體介紹之前,這裡需要首先注意兩點:

  1. 在每處理一個Http請求時,應用程式事件都會觸發一遍,但是Application_Start和 Application_End 例外,它僅在第一個資原始檔被訪問時被觸發。
  2. 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 請

HTTPHTTP概念介紹

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是什麽。 介紹這個概念之前,我們先來介紹一下什麽是規範,或規則。這裏我們舉個例子,交通規則。試想如果馬路上沒有交通規則,那麽交通擁堵的情況下,車輛和行人就不知道什麽時候自己該行走,那個