ASP.NET圖形驗證碼控制項

來源:互聯網
上載者:User
 在網頁上常把圖形驗證碼應用在登入或貼文的頁面中,因為圖形驗證碼具有機器不易識別的特性,可以防止機器人程式惡意的存取網頁。在本文中將實作一個圖形驗證碼的伺服器控制項,透過簡單的屬性設定就可以輕易地在網頁上套用圖形驗證碼。

   一、產生圖形驗證碼
  
   我們先準備一個產生圖形驗證碼的頁面 (ValidateCode.ASPx),這個頁面主要是繪製驗證碼圖形,並將其寫入記憶體資料流,最後使用 Response.BinaryWrite 將圖形輸出傳遞到用戶端。當我們輸出此驗證碼圖形的同時,會使用 Session("_ValidateCode") 來記錄驗證碼的值,以便後續與使用者輸入驗證碼做比對之用。
  
   Partial Class ValidateCode
   Inherits System.Web.UI.Page
  
   ''' <summary>
   ''' 產生圖形驗證碼。
   ''' </summary>
   ''' <param name="Code">傳出驗證碼。</param>
   ''' <param name="CodeLength">驗證碼字元數。</param>
   Public Function CreateValidateCodeImage(ByRef Code As String, ByVal CodeLength As Integer, _
   ByVal Width As Integer, ByVal Height As Integer, ByVal FontSize As Integer) As Bitmap
   Dim sCode As String = String.Empty
   '顏色列表,用於驗證碼、噪線、噪點
   Dim oColors As Color() = { _
   Drawing.Color.Black, Drawing.Color.Red, Drawing.Color.Blue, Drawing.Color.Green, _
   Drawing.Color.Orange, Drawing.Color.Brown, Drawing.Color.Brown, Drawing.Color.DarkBlue}
   '字體列表,用於驗證碼
   Dim oFontNames As String() = {"Times New Roman", "MS Mincho", "Book Antiqua", _
   "Gungsuh", "PMingLiU", "Impact"}
   '驗證碼的字元集,去掉了一些容易混淆的字元
   Dim oCharacter As Char() = {"2"c, "3"c, "4"c, "5"c, "6"c, "8"c, _
   "9"c, "A"c, "B"c, "C"c, "D"c, "E"c, _
   "F"c, "G"c, "H"c, "J"c, "K"c, "L"c, _
   "M"c, "N"c, "P"c, "R"c, "S"c, "T"c, _
   "W"c, "X"c, "Y"c}
   Dim oRnd As New Random()
   Dim oBmp As Bitmap
   Dim oGraphics As Graphics
   Dim N1 As Integer
   Dim oPoint1 As Drawing.Point
   Dim oPoint2 As Drawing.Point
   Dim sFontName As String
   Dim oFont As Font
   Dim oColor As Color
  
   '產生驗證碼字串
   For N1 = 0 To CodeLength - 1
   sCode += oCharacter(oRnd.Next(oCharacter.Length))
   Next
  
   oBmp = New Bitmap(Width, Height)
   oGraphics = Graphics.FromImage(oBmp)
   oGraphics.Clear(Drawing.Color.White)
   Try
   For N1 = 0 To 4
   '畫噪線
   oPoint1.X = oRnd.Next(Width)
   oPoint1.Y = oRnd.Next(Height)
   oPoint2.X = oRnd.Next(Width)
   oPoint2.Y = oRnd.Next(Height)
   oColor = oColors(oRnd.Next(oColors.Length))
   oGraphics.DrawLine(New Pen(oColor), oPoint1, oPoint2)
   Next
  
   For N1 = 0 To sCode.Length - 1
   '畫驗證碼字串
   sFontName = oFontNames(oRnd.Next(oFontNames.Length))
   oFont = New Font(sFontName, FontSize, FontStyle.Italic)
   oColor = oColors(oRnd.Next(oColors.Length))
   oGraphics.DrawString(sCode(N1).ToString(), oFont, New SolidBrush(oColor), CSng(N1) * FontSize + 10, CSng(8))
   Next
  
   For i As Integer = 0 To 30
   '畫噪點
   Dim x As Integer = oRnd.Next(oBmp.Width)
   Dim y As Integer = oRnd.Next(oBmp.Height)
   Dim clr As Color = oColors(oRnd.Next(oColors.Length))
   oBmp.SetPixel(x, y, clr)
   Next
  
   Code = sCode
   Return oBmp
   Finally
   oGraphics.Dispose()
   End Try
   End Function
  
   ''' <summary>
   ''' 產生圖形驗證碼。
   ''' </summary>
   ''' <param name="MemoryStream">記憶體資料流。</param>
   ''' <param name="Code">傳出驗證碼。</param>
   ''' <param name="CodeLength">驗證碼字元數。</param>
   Public Sub CreateValidateCodeImage(ByRef MemoryStream As MemoryStream, _
   ByRef Code As String, ByVal CodeLength As Integer, _
   ByVal Width As Integer, ByVal Height As Integer, ByVal FontSize As Integer)
   Dim oBmp As Bitmap
  
   oBmp = CreateValidateCodeImage(Code, CodeLength, Width, Height, FontSize)
   Try
   oBmp.Save(MemoryStream, ImageFormat.Png)
   Finally
   oBmp.Dispose()
   End Try
   End Sub
  
   Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
   Dim sCode As String = String.Empty
  
   '清除該頁輸出緩存,設置該頁無緩存
   Response.Buffer = True
   Response.ExpiresAbsolute = System.DateTime.Now.AddMilliseconds(0)
   Response.Expires = 0
   Response.CacheControl = "no-cache"
   Response.AppendHeader("Pragma", "No-Cache")
   '將驗證碼圖片寫入記憶體流,並將其以 "image/Png" 格式輸出
   Dim oStream As New MemoryStream()
   Try
   CreateValidateCodeImage(oStream, sCode, 4, 100, 40, 18)
   Me.Session("_ValidateCode") = sCode
   Response.ClearContent()
   Response.ContentType = "image/Png"
   Response.BinaryWrite(oStream.ToArray())
   Finally
   '釋放資源
   oStream.Dispose()
   End Try
   End Sub
   End Class  
   
   我們將此頁面置於 ~/Page/ValidateCode.ASPx,當要使用此頁面的圖形驗證碼,只需要在使用 Image 控制項,設定 ImageUrl 為此頁面即可。
  
   <asp:Image ID="imgValidateCode" runat="server" ImageUrl="~/Page/ValidateCode.aspx" />
   
   二、實作圖形驗證碼控制項
  
   雖然我們可以使用 Image 控制項來呈現 ValidateCode.ASPx 頁面產生的驗證碼圖形,可是這樣只處理一半的動作,因為沒有處理「使用者輸入的驗證碼」是否與「圖形驗證碼」相符,所以我們將實作一個圖形驗證碼控制項,來處理掉所有相關動作。
  
   即然上面的示範使用 Image 控制項來呈現驗證碼,所以圖形驗證碼控制項就繼承 Image 命名為 TBValidateCode。
  
   < _
   Description("圖形驗證碼控制項"), _
   ToolboxData("<{0}:TBValidateCode runat=server></{0}:TBValidateCode>") _
   > _
   Public Class TBValidateCode
   Inherits System.Web.UI.WebControls.Image
  
   End
   
   新增 ValidateCodeUrl 屬性,設定圖形驗證碼產生頁面的網址。
  
   ''' <summary>
   ''' 圖形驗證碼產生頁面網址。
   ''' </summary>
   < _
   Description("圖形驗證碼產生頁面網址"), _
   DefaultValue("") _
   > _
   Public Property ValidateCodeUrl() As String
   Get
   Return FValidateCodeUrl
   End Get
   Set(ByVal value As String)
   FValidateCodeUrl = value
   End Set
   End Property
   
   覆寫 Render 方法,若未設定 ValidateCodeUrl 屬性,則預設為 ~/Page/ValidateCode.ASPx 這個頁面。另外我們在圖形的 ondbclick 加上一段用戶端指令碼,其作用是讓使用者可以滑鼠二下來重新產生一個驗證碼圖形。
  
   Protected Overrides Sub Render(ByVal writer As System.Web.UI.HTMLTextWriter)
   Dim sUrl As String
   Dim sScript As String
  
   sUrl = Me.ValidateCodeUrl
   If String.IsNullOrEmpty(sUrl) Then
   sUrl = "~/Page/ValidateCode.ASPx"
   End If
   If Me.BorderWidth = Unit.Empty Then
   Me.BorderWidth = Unit.Pixel(1)
   End If
   If Me.AlternateText = String.Empty Then
   Me.AlternateText = "圖形驗證碼"
   End If
   Me.ToolTip = "雙擊即可重新生產驗證碼"
   Me.ImageUrl = sUrl
   If Not Me.DesignMode Then
   sScript = String.Format("this.src='{0}?flag='+Math.random();", Me.Page.ResolveClientUrl(sUrl))
   Me.Attributes("ondblclick") = sScript
   End If
   Me.Style(HTMLTextWriterStyle.Cursor) = "pointer"
  
   MyBase.Render(writer)
   End Sub  
   
   另外新增一個 ValidateCode 方法,用來檢查輸入驗證碼是否正確。還記得我們在產生驗證碼圖形時,同時把該驗證碼的值寫入 Session("_ValidateCode") 中吧,所以這個方法只是把使用者輸入的值與 Seesion 中的值做比對。
  
   ''' <summary>
   ''' 檢查輸入驗證碼是否正確。
   ''' </summary>
   ''' <param name="Code">輸入驗證碼。</param>
   ''' <returns>驗證承購返回 True,反之返回 False。</returns>
   Public Function ValidateCode(ByVal Code As String) As Boolean
   If Me.Page.Session(SessionKey) Is Nothing Then Return False
   If SameText(CCStr(Me.Page.Session(SessionKey)), Code) Then
   Return True
   Else
   Return False
   End If
   End Function
   
   三、測試程式
  
   在頁面放置一個 TBValidateCode 控制項,另外加一個文字框及按鈕,供使用者輸入驗證碼後按下「確定」按鈕後到服務端做輸入值比對的動作。
  
   <bee:TBValidateCode ID="TBValidateCode1" runat="server" />
   <bee:TBTextBox ID="txtCode" runat="server"></bee:TBTextBox>
   <bee:TBButton ID="TBButton1" runat="server" Text="確定" />
   
   在「確定」按鈕的 Click 事件中,我們使用 TBValidateCode 控制項的 ValidateCode 方法判斷驗證碼輸入的正確性。
  
   Protected Sub TBButton1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles TBButton1.Click
   If TBValidateCode1.ValidateCode(txtCode.Text) Then
   Me.Response.Write("驗證碼輸入正確")
   Else
   Me.Response.Write("驗證碼輸入錯誤!")
   End If
   End Sub
   
   執行程式,頁面就會隨機產生一個驗證碼圖形。
                                   
   輸入正確的值按「確定」鈕,就會顯示「驗證碼輸入正確」的訊息。因為我們在同一頁面測試的關係,你會發現 PostBack 後驗證碼圖形又會重新產生,一般正常的做法是驗證正確後就導向另一個頁面。
                                   
   當我們輸入錯誤的值,就會顯示「驗證碼輸入錯誤!」的訊息。
                                  

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.