【分析最原始驗證碼生成】HTTP請求處理程序


      我們知道,在ASP.NET中,所有的請求都要進過HttpApplication的處理管道,具體請參見DebugLZQ前面的博文。在服務器處理請求的過程中,實際的請求處理時通過處理程序來完成的,在HttpApplication的第11個事件(PreRequestHandlerExecute)之后,將會調用處理程序來處理請求。

      這是很有道理的,因為請求都要經過這個處理管道,但是,請求的內容是多種多樣的,應該對每種不同的請求映射不同的處理程序,這個ASP.NET處理的基本思想。正是由於請求的多種多樣,因此,在HttpApplication的處理管道中,適合處理針對所有請求的通用處理,比如檢查當前請求的用戶身份等,並不適合直接處理情求的內容並返回處理的結果。針對不同請求的不同處理,在ASP.NET中通過各種處理程序來分別進行處理。通常情況下,根據請求的擴展名來確定適用的處理程序,根據常見的請求類型,在ASP.NET中已經與定義了許多的處理程序。

      請求的真正處理是在處理程序這個環節,那么,HttpApplication的作用是什么呢?我們可以將它看作請求到達處理程序和離開處理程序的一個管道,這個管道提供了統一處理所有請求的機制,使得我們可以在請求被真正處理之前和處理之后進行預處理和處理后的工作,在有些網站處理技術中,被稱為過濾器(Filter)。ASP.NET通過大量的HttpApplication事件,這些事件按照固定的次序依次處罰,使得我們可以方便地開發出針對請求不同處理環節的過濾器。

       處理程序則負責完成實際的請求處理工作,對於網站開發程序員來說,大多數的開發工作是圍繞着處理程序展開的。實際上,接觸到HttpApplication事件處理的時候並不多,處理程序在不同的網站開發技術中,有着不同的名稱,在ASP.NET中,稱為HttpHandler。  

       在ASP.NET中,所有的處理程序類必須實現IHttpHandler接口或者實現 IHttpAsyncHandler接口,這兩個接口的區別是前者是一個同步接口,后者是一個異步處理模式的接口。這兩個接口都定義在命名空間System.Web下。

IHttpHandler的定義如下(大家都很熟悉吧!!!):  

     · ProcessRequest是這個接口的主要方法,接受一個HttpContext類型的請求上下文對象,通過這個對象,處理程序可以得到關於處理請求所需的信息,通過這個參數的Response屬性可以得到管理回應的對象,用以向客戶端返回服務器處理的結果。       

     · IsResuable屬性表示當這個處理程序對象在使用之后,是否還可以被緩存起來,在以后的請求處理中再次使用,這個屬性主要用來配合處理程序工廠使用。

      處理程序是ASP.NET網站中處理請求的基本單位,在默認情況下,處理程序中,甚至不能使用會話狀態,這樣可以提高網站處理的速度。對於需要讀寫會話狀態的處理程序,必須實現一個特定的接口IRequiresSessionState,這個接口定義在命名空間System.Web.SessionState中,其中沒有定義任何成員,所以實現這個接口並不需要在類中增加任何成員。與此類似,同樣定義在這個命名空間下的接口 IReadOnlySessionState 也沒有定義任何成員,用來標識只需讀取會話狀態的處理程序。       

      這種沒有任何成員的接口,通常被稱為標記接口,由於在.NET中類只有單繼承,但是可以實現多個接口,所以在.NET開發早期的時候出現過一些通過標記接口來表示類的某些特征的開發技巧。但是.NET平台上提供了一個更加直接簡單的技術來解決這種問題,這就是標簽(Attribute),所以,這種用法曇花一現,現在很少出現。在ASP.NET開發中,這是僅有的一例。

       每一種處理程序用來處理一類的請求,不同的請求類別通過請求的擴展名來進行區分,處理程序與請求之間的匹配關系在網站的配置文件web.config中通過配置參數進行設置。system.web配置元素的子元素 httpHandlers 用來配置網站所使用的處理程序。httpHandlers元素可以包含三種子元素:add、remove、clear。
      add子元素有三個必選的屬性,作用如下:     

      · verb 通過一個逗號(,)分隔的HTTP請求類型列表來表示處理請求的類型,例如GET,POST等;使用型號(*)表示處理所有類型的請求。     

      · path 通過一個固定的URL路徑或者一個使用型號(*)的通配符來匹配請求的URL,例如,使用*.aspx表示這個處理程序將處理所有擴展名為aspx的請求。     

      · type 處理程序 的類型名稱,或者是處理程序工廠的類型名稱,這個類型必須是類型的全名,如果類定義在一個命名空間中,那么必須包含這個命名空間,如果定義在一個私有的應用程序集中,那么必須在類名之后,通過附加一個逗號(,)分隔的程序集名稱,這個程序集的擴展名可以省略     

      validate為可選的屬性,如果設置為false,那么ASP.NET在第一次匹配的請求調用之前將不會試圖加載這個類。

      在網站應用程序運行的時候,實際得到的配置文件來自於系統能夠的machine.config,系統的web.config 和網站自身的web.config合並!(記住哦,O(∩_∩)O)

      在web.config中ASP.NET已經預先配置了57中處理程序的映射,程序員可以通過處理程序接口擴展自定義的處理程序。

      博友聲音:好了,說了這么多來個例子來說明下吧,學以致用嘛!!

      DebugLZQ:OK,馬上開始。DebugLZQ就使用最原始的處理程序生成驗證碼!當然用一般處理程序會簡化很多,廢話,一般處理程序就是用來簡化處理程序的!!!!還有其他很多處理程序,頁面處理程序Web服務處理程序MVC處理程序資源處理程序。。。。其實都是對處理程序的簡化。

      完成這個處理程序,需要以下幾個步驟:

          1)創建一個類庫項目 MyHandler,這個項目的默認命名空間也是 MyHandler

          2)類庫項目MyHandler中添加一個新類ValidateCodeHandler,實現IHttpHandler接口,為了在處理程序中使用Session狀態管理,同時實現IRequiresSessionState接口。

          3)在ProcessRequest方法中完成驗證碼生成的操場。

          4)在網站項目中引用類庫項目。

          5)在網站配置文件web.config中注冊這個處理程序。

          6)在需要驗證碼的頁面上使用處理程序生產的驗證碼。

      下面給出處理程序生成驗證碼的代碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyHandler
{
public class ValidateCodeHandler : System.Web.IHttpHandler,
System.Web.SessionState.IRequiresSessionState
{
private static System.Random random = new Random();
public void ProcessRequest(System.Web.HttpContext context)
{
context.Response.ContentType = "image/jpeg";

System.Drawing.Image image = new System.Drawing.Bitmap(60, 30);

// 生成隨機數
int code = random.Next(1000, 10000);
string codeString = code.ToString();

// 使用會話狀態
context.Session["Code"] = codeString;

using (System.Drawing.Graphics g
= System.Drawing.Graphics.FromImage(image))
{
g.Clear(System.Drawing.Color.WhiteSmoke);
System.Drawing.StringFormat sf
= new System.Drawing.StringFormat();
sf.Alignment = System.Drawing.StringAlignment.Center;
sf.LineAlignment = System.Drawing.StringAlignment.Center;
g.DrawString(
codeString,
new System.Drawing.Font("Arial", 14),
System.Drawing.Brushes.Blue,
new System.Drawing.RectangleF(0, 0,
image.Width, image.Height),
sf
);
}

context.Response.ContentType = "image/jpeg";
image.Save(
context.Response.OutputStream,
System.Drawing.Imaging.ImageFormat.Jpeg
);

}
public bool IsReusable
{
get
{
return false;
}
}
}
}

      (簡單的GDI+代碼,這個不是重點,但是DebugLZQ還是奉上!)

      處理程序在網站中得配置,如下(說明:在web.config <configuration><system.web>下添加配置):     

 <!-- 添加這個配置節-->
<httpHandlers>
<add verb="*" path="*.vc" type="MyHandler.ValidateCodeHandler,MyHandler"/>
</httpHandlers>

      好了,下面是如何使用。很簡單,在頁面中需要驗證碼的地方添加類似下面的代碼:

<asp:Image ID="Image1" runat="server"  ImageUrl="a.vc"/>

      DebugLZQ的必要的說明,其實並不存在"a.vc"這個東東,取得是其擴展名。

      好了,看下效果:

      好了,完成!

      博友心聲:DebugLZQ,何必這么麻煩呢?!為了生成驗證碼,我們緊緊需要在網站中得增加一個一般處理程序,然后,在ProcessRequest方法中實現功能就可以了。這樣,原來的1、2、4、5步都可以省略了!!!!!

      DebugLZQ:是的,是這樣子的,謝謝你的意見!DebugLZQ的寫博文的初衷是讓各位博友理解其中最為本質、最為原始的原理,請多多支持啊(O(∩_∩)O哈哈~)

       【請點擊下面的綠色通道關注DebugLZQ,與DebugLZQ共同學習進步!】


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM