利用 IHttpModule 自定義 HTTP 處理模塊

来源:http://www.cnblogs.com/androidshouce/archive/2016/06/14/5582716.html
-Advertisement-
Play Games

本文內容 引入 IHttpModule 概述 創建自定義 HTTP 模塊的步驟 演示創建自定義 HTTP 模塊 HTTP 模塊的工作方式 HTTP 模塊與 Global.asax 文件 參考資料 引入 本文在 VS 2008 和 IIS 6 環境下概述如何利用 IHttpModule 自定義 HTT ...


本文內容

  • 引入
  • IHttpModule 概述
  • 創建自定義 HTTP 模塊的步驟
  • 演示創建自定義 HTTP 模塊
  •     HTTP 模塊的工作方式
  •     HTTP 模塊與 Global.asax 文件
  • 參考資料

 

引入

本文在 VS 2008 和 IIS 6 環境下概述如何利用 IHttpModule 自定義 HTTP 模塊。

當我們在 VS 2008 里新建一個 Web 應用程式項目後,會在 Web.config 文件看到如下一個配置:

<httpModules>
  <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
</httpModules>

我們知道 VS 2008 已經可以開發 Ajax 程式,非同步刷新界面,如 ScriptManager 控制項、UpdatePanel 控制項,那麼 System.Web.Handlers.ScriptModule 類就是管理用於 ASP.NET 中 AJAX 功能的 HTTP 模塊。

更進一步,看它 C# 聲明:

[AspNetHostingPermissionAttribute(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermissionAttribute(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
public class ScriptModule : IHttpModule

該類繼承了 IHttpModule 介面。代碼如下所示。看看它的事件,你多少體會出如若讓 Web 應用程式支持 Ajax 功能,發出非同步請求,需要做什麼,至少能夠檢查傳入和傳出的請求。

//
// ScriptModule.cs
//
// Author:
//   Igor Zelmanovich <[email protected]>
//
// (C) 2007 Mainsoft, Inc.  http://www.mainsoft.com
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
 
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Web.Script.Services;
 
namespace System.Web.Handlers
{
    public class ScriptModule : IHttpModule
    {
        protected virtual void Init (HttpApplication context) {
            context.PreSendRequestHeaders += new EventHandler (PreSendRequestHeaders);
            context.PostAcquireRequestState += new EventHandler (PostAcquireRequestState);
            context.AuthenticateRequest += new EventHandler (AuthenticateRequest);
        }
 
        void AuthenticateRequest (object sender, EventArgs e) {
            // The AuthenticateRequest event is raised after the identity of the current user has been 
            // established. The handler for this event sets the SkipAuthorization property of the HttpContext 
            // for the current request. This property is checked in the authorization module to see 
            // if it has to omit authorization checking for the requested url. Usually an HttpModule 
            // use this property to allow anonymous access to some resources (for example, 
            // the Login Page if we’re using forms authentication). In our scenario, 
            // the ScriptModule sets the SkipAuthorization to true if the requested url is 
            // scriptresource.axd or if the authorization module is enabled and the request is a rest 
            // request to the authorization web service.
        }
 
        void PostAcquireRequestState (object sender, EventArgs e) {
            // The PostAcquireRequestState event is raised after the session data has been obtained. 
            // If the request is for a class that implements System.Web.UI.Page and it is a rest 
            // method call, the WebServiceData class (that was explained in a previous post) is used 
            // to call the requested method from the Page. After the method has been called, 
            // the CompleteRequest method is called, bypassing all pipeline events and executing 
            // the EndRequest method. This allows MS AJAX to be able to call a method on a page 
            // instead of having to create a web service to call a method.
            HttpApplication app = (HttpApplication) sender;
            HttpContext context = app.Context;
            if (context == null)
                return;
            
            HttpRequest request = context.Request;
            string contentType = request.ContentType;
            IHttpHandler currentHandler = context.CurrentHandler;
            if (currentHandler == null)
                return;
#if TARGET_J2EE
            if (!(currentHandler is Page) && currentHandler is IServiceProvider) {
                pageType = (Type) ((IServiceProvider) currentHandler).GetService (typeof (Type));
                if (pageType == null)
                    return;
            }
#endif
            Type pageType = currentHandler.GetType ();
            if (typeof (Page).IsAssignableFrom (pageType) && !String.IsNullOrEmpty (contentType) && contentType.StartsWith ("application/json", StringComparison.OrdinalIgnoreCase)) {
                IHttpHandler h = RestHandler.GetHandler (context, pageType, request.FilePath);
                h.ProcessRequest (context);
                app.CompleteRequest ();
            }
        }
 
        void PreSendRequestHeaders (object sender, EventArgs e) {
            HttpApplication app = (HttpApplication) sender;
            HttpContext context = app.Context;
            if (context.Request.Headers ["X-MicrosoftAjax"] == "Delta=true") {
                Page p = context.CurrentHandler as Page;
#if TARGET_J2EE
                if (p == null && context.CurrentHandler is IServiceProvider)
                    p = (Page) ((IServiceProvider) context.CurrentHandler).GetService (typeof (Page));
#endif
                if (p == null)
                    return;
                ScriptManager sm = ScriptManager.GetCurrent (p);
                if (sm == null)
                    return;
                if (context.Response.StatusCode == 302) {
                    context.Response.StatusCode = 200;
                    context.Response.ClearContent ();
                    if (context.Error == null || sm.AllowCustomErrorsRedirect)
                        ScriptManager.WriteCallbackRedirect (context.Response.Output, context.Response.RedirectLocation);
                    else
                        sm.WriteCallbackException (context.Response.Output, context.Error, false);
                }
                else if (context.Error != null) {
                    context.Response.StatusCode = 200;
                    context.Response.ClearContent ();
                    sm.WriteCallbackException (context.Response.Output, context.Error, true);
                }
            }
        }
 
        protected virtual void Dispose () {
        }
 
        #region IHttpModule Members
 
        void IHttpModule.Dispose () {
            Dispose ();
        }
 
        void IHttpModule.Init (HttpApplication context) {
            Init (context);
        }
 
        #endregion
    }
}

 

IHttpModule 概述

HTTP 模塊是一個在每次針對應用程式發出請求時調用的程式集。HTTP 模塊作為 ASP.NET 請求管道的一部分調用,它們能夠在整個請求過程中訪問生命周期事件。HTTP 模塊使您可以檢查傳入和傳出的請求並根據該請求進行操作。

HTTP 模塊通常具有以下用途:

  • 安全 因為您可以檢查傳入的請求,所以 HTTP 模塊可以在調用請求頁、XML Web services 或處理程式之前執行自定義的身份驗證或其他安全檢查。
  • 統計信息和日誌記錄 因為 HTTP 模塊是在每次請求時調用的,所以,您可以將請求統計信息和日誌信息收集到一個集中的模塊中,而不是收集到各頁中。
  • 自定義的頁眉或頁腳 因為您可以修改傳出響應,所以可以在每一個頁面或 XML Web services 響應中插入內容,如自定義的標頭信息。

 

創建自定義 HTTP 模塊的步驟

編寫 HTTP 模塊的一般過程如下:

  • 創建一個實現 IHttpModule 介面的類。
  • 實現 Init 方法。該方法初始化模塊,並創建所需的任何應用程式事件。例如,如果希望為響應附加一些內容,可以創建 EndRequest 事件。如果希望執行自定義身份驗證邏輯,可以創建 AuthenticateRequest 事件。
  • 為已創建的事件編寫代碼。
  • 若模塊需要釋放,還可以實現 Dispose 方法。
  • 在 Web.config 文件中註冊模塊。

 

演示創建自定義 HTTP 模塊

將一個字元串追加到響應的開頭和末尾。在對其擴展名已分配給 ASP.NET 的文件進行任何請求的過程中,該模塊都將自動運行。

  • 新建 Web 項目。
  • 新建名為 HelloWorldModule 的類,該類繼承 IHttpModule,如下所示:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
 
namespace HttpModuleDemo
{
    public class HelloWorldModule : IHttpModule
    {
        public HelloWorldModule()
        {
        }
 
        public String ModuleName
        {
            get { return "HelloWorldModule"; }
        }
 
        // In the Init function, register for HttpApplication 
        // events by adding your handlers.
        public void Init(HttpApplication application)
        {
            application.BeginRequest +=
                (new EventHandler(this.Application_BeginRequest));
            application.EndRequest +=
                (new EventHandler(this.Application_EndRequest));
        }
 
        private void Application_BeginRequest(Object source,
             EventArgs e)
        {
            // Create HttpApplication and HttpContext objects to access
            // request and response properties.
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;
            string filePath = context.Request.FilePath;
            string fileExtension =
                VirtualPathUtility.GetExtension(filePath);
            if (fileExtension.Equals(".aspx"))
            {
                context.Response.Write("<h1><font color=red>" +
                    "HelloWorldModule: Beginning of Request" +
                    "</font></h1><hr>");
            }
        }
 
        private void Application_EndRequest(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;
            string filePath = context.Request.FilePath;
            string fileExtension =
                VirtualPathUtility.GetExtension(filePath);
            if (fileExtension.Equals(".aspx"))
            {
                context.Response.Write("<hr><h1><font color=red>" +
                    "HelloWorldModule: End of Request</font></h1>");
            }
        }
 
        public void Dispose() { }
    }
}
  • 在 Web.config 文件註冊該模塊,如下所示:
<httpModules>
  <add name="HelloWorldModule" type="HttpModuleDemo.HelloWorldModule"/>
</httpModules>
  • 新建一個頁面,並用瀏覽器查看該頁面,頁面會顯示如下信息。

a

HTTP 模塊的工作方式

模塊必須註冊才能從請求管道接收通知。註冊 HTTP 模塊的最常用方法是在應用程式的 Web.config 文件中進行註冊。

當 ASP.NET 創建表示您的應用程式的 HttpApplication 類的實例時,將創建已註冊的任何模塊的實例。在創建模塊時,將調用它的 Init 方法,並且模塊會自行初始化。

當這些應用程式事件被引發時,將調用模塊中的相應方法。該方法可以執行所需的任何邏輯。如檢查身份驗證或記錄請求信息。在事件處理過程中,模塊能訪問當前請求的 Context 屬性。這使得可以將請求重定向到其他頁、修改請求或者執行任何其他請求操作。例如,若模塊檢查身份驗證,則在憑據不正確的情況下,模塊可能重定向到登錄頁或錯誤頁。否則,當模塊的事件處理程式完成運行時,ASP.NET 會調用管道中的下一個進程。這可能是另一個模塊,也可能是用於該請求的 HTTP 處理程式(如 .aspx 文件)。

HTTP 模塊與 Global.asax 文件

之所以把它們放在一起,是因為在某種程度上,它們功能有相似之處。

可以在應用程式的 Global.asax 文件中實現模塊的許多功能,這使你可以響應應用程式事件。但是,

  • 模塊相對於 Global.asax 文件具有如下優點:模塊可以進行封裝。創建一次後在其他應用程式中使用。通過將它們添加到全局程式集緩存,並將其註冊到 Machine.config 文件中,可以跨應用程式重新使用它們。
  • 使用 Global.asax 文件的好處在於可以處理其他已註冊事件,如 Session_Start 和 Session_End。此外,Global.asax 文件還允許您實例化可在整個應用程式中使用的全局對象。

當您必須創建依賴應用程式事件的代碼,並且符合以下條件時,都應該使用模塊:

  • 希望在其他應用程式中重用該模塊。
  • 希望避免將複雜代碼放在 Global.asax 文件中。
  • 該模塊應用於管道中的所有請求(僅限 IIS 7.0 集成模式)。

當您必須創建依賴應用程式事件的代碼並且不需要跨應用程式重用代碼時,應該將代碼添加到 Global.asax 文件中。當必須訂閱對於模塊不可用的事件(如 Session_Start)時,也可以使用 Global.asax 文件。

 

參考資料

MSDN HTTP 處理程式和 HTTP 模塊概述 http://msdn.microsoft.com/zh-cn/library/bb398986(v=VS.90).aspx

MSDN IHttpModule http://msdn.microsoft.com/zh-cn/library/system.web.ihttpmodule(v=VS.90).aspx

 

下載 Demo


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Linux下運行的Web伺服器Apache,預設日誌文件是不分割的,一個整文件既不易於管理,也不易於分析統計。安裝cronolog後,可以將日誌文件按時間分割,易於管理和分析。 cronolog安裝配置非常簡單,下載後只需要輸入幾個命令即可完成。 1、下載(最新版本) 如果這個鏈接失效,請上這個鏈接 ...
  • 總結一下上一個項目中對webapi 用戶登錄許可權控制的設計 目的:前端可以根據介面的狀態碼來判斷用戶的登錄狀態,以及訪問許可權 1.首先我們在webconfig裡面添加一條配置,用於開啟或關閉許可權控制 2.先瞭解一下 ActionFilterAttribute 這個類,該類可以在action方法執行前 ...
  • 1 環境搭建:安裝CAD 和objectArx庫,這裡安裝的是cad2012和objectArx2010 ,vs是2010 2 新建一個類庫項目,引用objectArx安裝目錄下inc文件夾下的AcDbMgd.dll和AcMgd.dll,這裡註意X86和X64系統的區別 3 添加兩個類,一個繼承IE ...
  • 在現今很多網站裡面,都使用了微信開放平臺的掃碼登錄認證處理,這樣做相當於把身份認證交給較為權威的第三方進行認證,在應用網站裡面可以不需要存儲用戶的密碼了。本篇介紹如何基於微信開放平臺的掃碼進行網站的登陸處理。 ...
  • "%~dp0",在BAT中,是不是“相對路徑”的意思 (2013-08-21 12:19:32) 轉載▼ "%~dp0",在BAT中,是不是“相對路徑”的意思 轉載▼ 標簽: 雜談 分類: C# 雜談 0念 零 ,代表你的批處理本身。 d p是FOR 命令的擴展。%~f0 將 %I 擴展到一個完全合 ...
  • 目錄: 支持操作系統 IIS配置 安裝。 網路核心Windows伺服器托管包 部署應用程式 在IIS配置網站 創建一個數據保護註冊表項 常見的錯誤 額外的資源 目錄: 支持操作系統 IIS配置 安裝。 網路核心Windows伺服器托管包 部署應用程式 在IIS配置網站 創建一個數據保護註冊表項 常見 ...
  • API: http://mp.weixin.qq.com/wiki/10/0234e39a2025342c17a7d23595c6b40a.html https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5 請求prepay_id得 ...
  • 序:在功能性比較強大的後臺管理網站處於各種角度考慮多有應用許可權管理功能。以公司內部管理系統為例,管理員根據不同員工所在不同部門賦予其不同許可權,或者根據上下級隸屬關係實現“金字塔”管理(註:本次所授許可權管理為不可動態編輯模式,即無法進行二級以上許可權分割)。本文內容有不盡不實之處懇請指正。 正文:如下效 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...