access_time 13 years ago language中文
more_vert

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

visibility 478 comment 2

由于现在的注册机、发帖机等垃圾软件实在太多,为了有效的拦截这些信息,许多站点都需要用到验证码,下面就用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是客户端也可以访问的

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

info Last modified by Raymond 13 years ago copyright This page is subject to Site terms.
Like this article?
Share on

Please log in or register to comment.

account_circle Log in person_add Register

Log in with external accounts

Follow Kontext

Get our latest updates on LinkedIn.

Want to contribute on Kontext to help others?

Learn more

More from Kontext

visibility 34
thumb_up 0
access_time 8 months ago
visibility 4406
thumb_up 0
access_time 3 years ago
visibility 1454
thumb_up 0
access_time 9 months ago