使用HttpHandler实现图片验证码

 

打开VS,添加一般处理程序(.ashx)。默认已经实现了IHttpHandler里的ProcessRequest方法和IsReusable属性,只需改变ProcessRequest里的方法即可。

(注:在此引用的是袁老师和张老师的例子,写出来呢,主要是学习)

袁老师:http://www.cnblogs.com/xdesigner/archive/2008/06/04/1213496.html

如果对验证码原理还不是很清楚的,请看看袁老师的链接。

张老师:http://www.cnblogs.com/JimmyZhang/archive/2007/09/15/894124.html

 

 //方法一:
<%@ WebHandler Language="C#" class="Handler" %>

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

public class Handler : IHttpHandler, IRequiresSessionState
{

    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "image/gif";
        //建立Bitmat对象,绘图
        Bitmap basemap = new Bitmap(200, 60);
        Graphics graph = Graphics.FromImage(basemap);
        graph.FillRectangle(new SolidBrush(Color.White), 0, 0, 200, 60);
        Font font = new Font(FontFamily.GenericSansSerif, 48, FontStyle.Bold, GraphicsUnit.Pixel);
        Random r = new Random();
        string letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        string letter;
        StringBuilder s = new StringBuilder();
        //添加随机的五个字母
        for (int i = 0; i < 5; i++)
        {
            letter = letters.Substring(r.Next(0, letters.Length - 1), 1);
            s.Append(letter);
            graph.DrawString(letter, font, new SolidBrush(Color.Black), i * 38, r.Next(0, 15));
        }
        //混淆背景
        Pen linePen = new Pen(new SolidBrush(Color.Black), 2);
        for (int i = 0; i < 6; i++)
        {
            graph.DrawLine(linePen, new Point(r.Next(0, 199), r.Next(0, 59)), new Point(r.Next(0, 199), r.Next(0, 59)));
        }
        //将图片保存到输出流中
        basemap.Save(context.Response.OutputStream, ImageFormat.Gif);
        context.Session["CheckCode"] = s.ToString();//如果没有实现IRequiresSessionState,则这里会出错,也无法生成图片
        context.Response.End();
    } 
    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

添加测试页面:

前台:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>无标题页</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <p align="center">
            <font face="宋体" size="6">ASP.NET验证码测试页面</font></p>
        <font face="宋体">验证码:
            <asp:TextBox ID="txtCheckCode" runat="server" Width="224px"></asp:TextBox>
            <img src="Handler.ashx" alt="图片验证码" ondblclick="this.src = 'Handler.ashx?flag=' + Math.random() "
                style="border: 2px;" />
            <!--
      这里的 ondblclick 代码中采用一个毫无意义的flag参数可有效的防止浏览器缓存图片
      使得显示的验证码图片一定是最新的图片
     -->
            <span>看不清楚,双击图片换一张。</span>
         </font>
         <p>
        <asp:Button ID="cmdOK" runat="server" Text="点击得到上一个验证码" OnClick="cmdOK_Click"></asp:Button>
        </p>
        <asp:Label ID="lblResult" runat="server"></asp:Label>
    </div>
    </form>
</body>
</html>

 后台:

using System;
using System.Data;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {}
    protected void cmdOK_Click(object sender, EventArgs e)
    {
        if (System.Web.HttpContext.Current.Session["CheckCode"] != null)
        {
            lblResult.Text = System.Web.HttpContext.Current.Session["CheckCode"] as string;
        }
    }
}

结果:

 

//方法二:
<%@ WebHandler Language="C#" class="Handler" %>

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

public class Handler : IHttpHandler, IRequiresSessionState
{

    public void ProcessRequest(HttpContext context)
    {

        // 创建一个包含随机内容的验证码文本
        Random rand = new Random();
        int len = rand.Next(4, 6);
        char[] chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
        StringBuilder myStr = new StringBuilder();
        for (int iCount = 0; iCount < len; iCount++)
        {
            myStr.Append(chars[rand.Next(chars.Length)]);
        }
        string text = myStr.ToString();
        Size ImageSize = Size.Empty;
        Font myFont = new Font("MS Sans Serif", 20);
        // 计算验证码图片大小
        using (Bitmap bmp = new Bitmap(10, 10))
        {
            using (Graphics g = Graphics.FromImage(bmp))
            {
                SizeF size = g.MeasureString(text, myFont, 10000);
                ImageSize.Width = (int)size.Width + 1;
                ImageSize.Height = (int)size.Height + 1;
            }
        }
        // 创建验证码图片
        using (Bitmap bmp = new Bitmap(ImageSize.Width, ImageSize.Height))
        {
            // 绘制验证码文本
            using (Graphics g = Graphics.FromImage(bmp))
            {
                g.Clear(Color.White);
                using (StringFormat f = new StringFormat())
                {
                    f.Alignment = StringAlignment.Near;
                    f.LineAlignment = StringAlignment.Center;
                    f.FormatFlags = StringFormatFlags.NoWrap;
                    g.DrawString(
                        text,
                        myFont,
                        Brushes.Black,
                        new RectangleF(
                        0,
                        0,
                        ImageSize.Width,
                        ImageSize.Height),
                        f);
                }
            }

            // 制造噪声 杂点面积占图片面积的 30%
            int num = ImageSize.Width * ImageSize.Height * 30 / 100;

            for (int iCount = 0; iCount < num; iCount++)
            {
                // 在随机的位置使用随机的颜色设置图片的像素
                int x = rand.Next(ImageSize.Width);
                int y = rand.Next(ImageSize.Height);
                int r = rand.Next(255);
                int g = rand.Next(255);
                int b = rand.Next(255);
                Color c = Color.FromArgb(r, g, b);
                bmp.SetPixel(x, y, c);
            }

            // 输出图片
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
            context.Response.ContentType = "image/Gif";
            context.Session["CheckCode"] = text;
            ms.WriteTo(context.Response.OutputStream);
            ms.Close();
        }
        myFont.Dispose();
    }
    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

 测试页面同上。

 

注:从本质上讲,两种方法是一样的,在此只是让自己多明白理解而已。

 

posted @ 2012-02-24 23:09  烁星  阅读(782)  评论(0编辑  收藏  举报