This site uses cookies to deliver our services. By using this site, you acknowledge that you have read and understand our Cookie and Privacy policy. Your use of Kontext website is subject to this policy. Allow Cookies and Dismiss

用HttpHandler实现asp.net 的验证码功能

230 views 2 comments last modified about 10 years ago Raymond Tang

由于现在的注册机、发帖机等垃圾软件实在太多,为了有效的拦截这些信息,许多站点都需要用到验证码,下面就用HttpHandler实现的验证码机制

/* ***********************************************
* Author:          1987raymond
* Team:            Juice Sharing
* Created Time:    2009-3-10 19:22:46
* CopyRight:       Juice Sharing 团队版权所有 保留一切权利
* NameSpace:       Juice.Common.HttpHandlers
* Class/Interface: ValidateCodeRender
* ***********************************************/

using System;
using System.Text;
using System.Web;
using System.Drawing;
using System.Drawing.Imaging;
using System.Web.SessionState;

namespace Juice.Common.HttpHandlers
{
    /// <summary>
    /// 验证码生成器
    /// </summary>
    public sealed class ValidateCodeRender : IHttpHandler, IRequiresSessionState
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public ValidateCodeRender()
        { }

        #region 私有字段

        /// <summary>
        /// 验证码的长度
        /// </summary>
        private int m_CodeLength = 5;

        /// <summary>
        /// 保存到会话状态中的值
        /// </summary>
        private string m_SessionName = "validateCode";

        /// <summary>
        /// 图像的宽
        /// </summary>
        private int m_ImageWidth = 160;

        /// <summary>
        /// 图像的长
        /// </summary>
        private int m_ImageHeight = 60;

        /// <summary>
        /// 图像背景色
        /// </summary>
        private Color m_BackgroundColor = Color.FromArgb(212, 236, 189);

        /// <summary>
        /// 图像上验证码的颜色
        /// </summary>
        private Color m_CodeColor = Color.FromArgb(132, 199, 1);

        /// <summary>
        /// 干扰图形的颜色
        /// </summary>
        private Color m_ObstructionColor = Color.Gray;

        /// <summary>
        /// 用来生成随机验证码的字符串
        /// </summary>
        private const string m_CodeString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890我和你的大小";

        #endregion

        #region IHttpHandler 成员

        /// <summary>
        /// 是否可以重用
        /// </summary>
        public bool IsReusable
        {
            get { return true; }
        }

        /// <summary>
        /// 处理请求
        /// </summary>
        /// <param name="context"></param>
        public void ProcessRequest(HttpContext context)
        {
            ///设置输出的格式
            context.Response.ContentType = "image/gif";
            Random random = new Random();
            ///用来保存随机取得的字符串
            StringBuilder s = new StringBuilder();
            ///创建绘图的图像
            using (Bitmap bitmap = new Bitmap(this.m_ImageWidth, this.m_ImageHeight))
            {
                ///创建绘图图面,用此对象将各种符号等绘制到制定的图像上
                using (Graphics graphics = Graphics.FromImage(bitmap))
                {
                    ///生成背景颜色
                    graphics.FillRectangle(new SolidBrush(this.m_BackgroundColor), 0, 0, this.m_ImageWidth, this.m_ImageHeight);

                    #region 生成验证码
                    ///验证码的字体
                    using (Font font = new Font(FontFamily.GenericSerif, 32, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Pixel))
                    {
                        for (int i = 0; i < this.m_CodeLength; i++)
                        {
                            s.Append(ValidateCodeRender.m_CodeString.Substring(random.Next(0, m_CodeString.Length - 1), 1));
                            ///将字符绘制到图像上
                            graphics.DrawString(s[s.Length - 1].ToString(), font, new SolidBrush(this.m_CodeColor), i * 32, random.Next(0, 24));

                        }
                    }
                    #endregion

                    #region 绘制干扰图形和噪点

                    //干扰图形绘制画笔
                    using (Pen pen = new Pen(new SolidBrush(this.m_ObstructionColor), 1))
                    {
                        for (int i = 0; i < 10; i++)
                        {
                            graphics.DrawLine(pen, new Point(random.Next(0, this.m_ImageWidth - 1), random.Next(0, this.m_ImageHeight - 1)), new Point(random.Next(0, this.m_ImageWidth - 1), random.Next(0, this.m_ImageHeight - 1)));

                        }
                    }
                    for (int i = 0; i < 100; i++)
                    {

                        bitmap.SetPixel(random.Next(this.m_ImageWidth), random.Next(this.m_ImageHeight), Color.FromArgb(random.Next()));
                    }


                    #endregion

                    ///保存图像到输出流
                    bitmap.Save(context.Response.OutputStream, ImageFormat.Gif);
                }
            }
            ///将验证码的值保存到用户会话状态中,并且不区分大小写
            context.Session[this.m_SessionName] = s.ToString().ToLower();
            context.Response.End();
        }

        #endregion
    }
}

上面这个类就是绘制验证码图像并且输出到页面的类,它实现了IHttpHandler接口

下面再到web.config的 <httpHandlers>节点中添加此项:
      <add verb="GET" path="ValidateCode.aspx" validate="false" type="Juice.Common.HttpHandlers.ValidateCodeRender,Juice.Common" />

Juice.Common.HttpHandlers.ValidateCodeRender,Juice.Common 根据你自己的情形而定

下面则是在具体的页面中调用:

测试验证码:<img src="/ValidateCode.aspx" alt="验证码" id="validateCode" /><a
                    href="javascript:refreshCode();">刷新验证码</a>
<script language="javascript" type="text/javascript">
                function refreshCode()
                {
                var e=gid("validateCode");
                e.src="/ValidateCode.aspx"+"?t="+new Date().toTimeString();
                }
                </script>
效果如下图所示:

大家注意下这个地方:

///将验证码的值保存到用户会话状态中,并且不区分大小写
            context.Session[this.m_SessionName] = s.ToString().ToLower();

我是把验证码保存在Session中的,所以如果你需要检查某个用户输入是否正确就只需看其值和Session中的值是不是一样的

同时有一点注意下就是我看到一些网上教程所把验证码的值保存在Cookie中,我想这样做是错误的,而且丧失了验证码的功能,因为Cookie是客户端也可以访问的

大家还可以扩展验证码 的内容,比如改成算术等等的形式

Related pages

Set AttachDbFilename as Relative Path in .NET Core

148 views   0 comments last modified about 3 months ago

.NET Framework, you can use |DataDirectory| to configure connection string when connecting to SQL Server database file via attach mode: AttachDbFilename=|DataDirectory|\dbname.mdf In .NET Core, you cannot directly set SQL Server Express connec...

View detail

Instantiate a Service in ConfigureServices Method in .NET Core

31 views   0 comments last modified about 3 months ago

.NET Core is built in with dependency injection. Usually method ConfigureServices in Startup class is used to register services in the container. The signature of the method looks like the following: public void ConfigureServices(IServiceC...

View detail

SQLite in .NET Core with Entity Framework Core

86 views   0 comments last modified about 3 months ago

SQLite is a self-contained and embedded SQL database engine. In .NET Core, Entity Framework Core provides APIs to work with SQLite. This page provides sample code to create a SQLite database using package Microsoft.EntityFrameworkCore.Sqlite . Create sample project ...

View detail

Graphics Programming and Image Processing in .NET Core 2.x

50 views   0 comments last modified about 3 months ago

In .NET Core 2.x, Windows Forms or WPF are not implemented since they are based on GDI+ and DirectX respectively in Windows. In .NET Core 3.0, there is plan to add Desktop Packs which includes UWP. WPF and Windows Forms. However, they will still be Windows-only. In .NET Core applications, you may...

View detail

Tuples in C# (4.x, 7.0, 7.1)

161 views   0 comments last modified about 7 months ago

What is a tuple? Tuple is an ordered sequence, fixed-size, immutable and of heterogeneous objects. Tuple has been existing in other languages such as F#, Python, Perl and etc. for a long time. It was first introduced into C# from C# 4.0 and has been evolving over time. Since C# 7.1, tuple...

View detail

Invoke Hadoop WebHDFS APIs in .NET Core

311 views   0 comments last modified about 7 months ago

Background Apache doesn't provide native official .NET APIs for Hadoop HDFS. The HTTP REST API supports the complete FileSystem / ...

View detail

Add comment

Please login first to add comments.  Log in New user?  Register

Comments (2)

R Re:用HttpHandler实现asp.net 的验证码功能

Ra*** about 6 years ago

@小小小菜鸟 你好 能否将你的代码贴出来,这样帮你分析。我的此验证码功能已经改用到在线网站Mvc用的版本
re: 用HttpHandler实现asp.net 的验证码功能

小小*** about 7 years ago

请问 我也做了一个类似的验证码 img标签 但是 每次ajax刷新的时候 都要提交两次 后来找到是img标签的问题
把img标签屏蔽了 就不会屏蔽了 就不会重复提交 请问 怎么img标签在页面的时候防止ajax重复提交