在网页上常把图形验证码应用在登入或贴文的页面中,因为图形验证码具有机器不易识别的特性,可以防止机器人程序恶意的存取网页。在本文中将实作一个图形验证码的服务器控件,透过简单的属性设定就可以轻易地在网页上套用图形验证码。

程序代码下载:ASP.NET Server Control - Day28.rar

一、产生图形验证码

我们先准备一个产生图形验证码的页面 (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 后验证码图形又会重新产生,一般正常的做法是验证正确后就导向另一个页面。

当我们输入错误的值,就会显示「验证码输入错误!」的讯息。

备注:本文同步发布于「第一届iT邦帮忙铁人赛」,如果你觉得这篇文章对您有帮助,记得连上去推鉴此文增加人气 ^^
http://ithelp.ithome.com.tw/question/10013361
http://ithelp.ithome.com.tw/question/10013365

转载于:https://www.cnblogs.com/jeff377/archive/2008/10/29/1322471.html

[ASP.NET 控件实作 Day28] 图形验证码控件相关推荐

  1. [ASP.NET 控件实作 Day14] 继承 CompositeControl 实作 Toolbar 控件

    之前我们简单介绍过继承 CompositeControl  来实作复合控件,在本文我们将以 Toolbar 控件为例,以复合控件的作法(继承 CompositeControl )来实作 Toolbar ...

  2. ASP.NET下英文及中文汉字的验证码控件

    本文转自http://bbs.msproject.cn/Default.aspx?g=posts&t=660 翻译 Nataraj K. 著Image Verifier - Custom Co ...

  3. 工控软件图形界面-控件实现(圆形仪表控件三)(zz)

    介绍 在工业控制系统开发过程中,图形显示方面占有着很重要的作用.比起很多专用的组态软件,他们有着强大的在图形系统,能够组态出来非常漂亮的系统.现在的很多的工业图形开发包都需要支付费用,很多漂亮的控件比 ...

  4. ImageGear for .NET扫描打印等图形图像处理控件介绍使用手册

    ImageGear for .NET是一款图形图像处理控件,具有扫描,压缩,浏览.添加注释,打印,图像编辑,OCR以及PDF和矢量图像支持,使开发人员可以快速地开发出图像处理程序,可用于.NET Fr ...

  5. .NET下的图形绘制控件

    图形图表的可视化数据表现形式已成为一种趋势.因为图表能直观的展示信息.对比和趋势等,所以许多项目开发中都需要用到图表控件,而很多图表控件都是在.NET平台下开发的,下面是做得比较好的10款图形图表控件 ...

  6. 雕虫小技--验证码控件

    转:http://www.cnblogs.com/wmj/archive/2008/04/17/1158662.html 主题  雕虫小技--自定义"验证码"控件 "验证 ...

  7. Asp.net控件之异同:HTML控件与Web服务器控件

    Asp.net之所以现在开发方便和快捷,关键是它有一组强大的控件库,包括web服务器控件,web用户控件,web自定义控件,html服务器控件和html控件等.这里我主要说说html控件.html服务 ...

  8. ASP.NET 2.0 中的 DataSource 系列控件

    在ASP.NET 2.0中,引入了DataSource系列控件,扔一个到页面上并且选择性的配置好SELECT/UPDATE/INSERT/DELETE对应的操作,它就能够和数据空间无缝合作自动处理查询 ...

  9. [转]【无私分享:ASP.NET CORE 项目实战(第十四章)】图形验证码的实现

    本文转自:http://www.cnblogs.com/yuangang/p/6000460.html 目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 很长时间没有来更新博客 ...

最新文章

  1. 取代百度!美团成中国第三大互联网公司
  2. 【洛谷P1381】单词背诵
  3. Lucene系列:(9)搜索结果排序
  4. java找出一组数据缺少最小数组_Java获取一维数组的最小值实现方法
  5. mysql三大范式 答案_数据库逻辑设计之三大范式通俗理解,一看就懂,书上说的太晦涩...
  6. linux jdk1.8 32位下载永久地址,ubuntu,centos,java
  7. poj2236 并查集
  8. 后flash时代的何去何从
  9. 拉里 埃里森_拉里·沃尔(Larry Wall)的“程序员的三个美德”是胡说八道
  10. 不是抽象的, 并且未覆盖Handler中的抽象方法
  11. 浅谈Thumbnails压缩gif图片质量的实现方式
  12. PDF可以被压缩吗,是如何实现的?
  13. python读取加密word_Python 实现加密过的PDF文件转WORD格式
  14. 推荐:电脑蓝屏代码分析工具BlueScreenView简体中文版下载
  15. docker上部署nginx容器80端口自动转443端口
  16. After Effects CC 2019 Essential Training: The Basics After Effects CC 2019基础教程:基础知识 Lynda课程中文字幕
  17. 猛学亚马逊:顾客至上 Obsession over customers
  18. 解决U盘在Linux系统只读的问题:[sdb] Write cache: disabled, read cache: enabled, doesn‘t support DPO or FUA
  19. cesium实现三维空间量测功能
  20. 线程池的五种状态详解

热门文章

  1. [机器学习]信息熵信息增益
  2. Jenkins搭建的几个坑记下
  3. 如何解决多线程并发问题
  4. 【419天】跃迁之路——程序员高效学习方法论探索系列(实验阶段176-2018.03.31)...
  5. 第七阶段 jsp(369---el---jstl)
  6. Windows7 VMware虚拟机安装Apple Mac OSX v10.7 Lion
  7. 使用PHP开发的Docker前端web管理平台!
  8. 什么是指针?什么是数组?指针和数组的关系?
  9. hdoj_1047_大數加法 java 模擬
  10. 什么是服务质量(QoS) ?—Vecloud微云