BosonZhang's Blog



    不积跬步,无以至千里;不积小流,无以成江海。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

浅谈验证码生成

Posted on 2008-07-24 23:44  qdzhbsh  阅读(1477)  评论(0)    收藏  举报

      验证码是现在大多数网站、论坛用到的为防止非法登录和非法提交信息的一种方法,其实它的实现并不复杂。下面就举个简单例子做一说明,生成的是包含字母和数字组合的验证码。

      首先在一个测试页面上,放一个img标记,然后将它的src属性指向一个验证码页面,用来得到输出的验证码图片的二进制流。接下来在验证码页面的Page_Load方法中调用一个验证码类的CreateValidateGraphic方法就可以了,这个方法需要传一个Page类型的参数。大体实现过程就是这样,另外如果要更换一张验证码图片,可以点击一下“刷新”,调用一个JavaScript方法,重置一下img标记的src属性就可以了。后附相关代码。

 

 ----------测试页面 Test1.aspx----------

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

<!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>

<script language="javascript" type="text/javascript">
    //更换验证码
    function Change()
    {
         var img_ValidateCode=document.getElementById("img_ValidateCode"); 
         var timeStamp = new Date().getTime();
         img_ValidateCode.src="/Web/Test/ValidateCode.aspx?timeStamp=" + timeStamp;
    }
</script>   

</head>
<body>
    <form id="form1" runat="server">
           <table width="100%" border="0" cellspacing="0" cellpadding="0">
                 <tr>
                      <td width="19%">&nbsp;</td>
                      <td width="60%">
                           <img id="img_ValidateCode" name="img_ValidateCode" src="ValidateCode.aspx" width="146" height="37" alt="看不清验证码请点击刷新">
                       </td>
                       <td width="21%" valign="bottom" align="center">
                            <a onclick="Change()" style="cursor:hand">刷新</a>
                       </td>
                  </tr>
         </table>
    </form>
</body>
</html>

----------验证码页面后台文件 ValidateCode.aspx.cs----------

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using Solution.PublicLib;

 

public partial class Test_ValidateCode : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        ValidateCode vc = new ValidateCode(146, 37, 5, 17f);

        vc.CreateValidateGraphic(this);

        Session["ValidateCodes"] = vc.ValidateCodes;

    }
}

----------验证码类 ValidateCode.cs----------

using System;
using System.Collections.Generic;
using System.Text;

using System.Drawing;
using System.Drawing.Imaging;
using System.Web.UI;
using System.Drawing.Drawing2D;
using System.IO;

 

namespace Solution.PublicLib
{
    /// <summary>
    /// 验证码类
    /// </summary>
    public class ValidateCode
    {
        //验证码图片的长度
        private int _imageWidth = 0;

        //验证码图片的高度
        private int _imageHeight = 0;

        //验证码字符串的长度
        private int _codeLength = 0;

        //新字体的全身大小(以磅值为单位)
        private float _emSize = 0f;


         //存放所有验证码字符串的数组 屏蔽"0"和"O"
        private string[] _fullCodes ={ "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };

 

        //存放生成的验证码字符串的数组
        private string[] _validateCodes = null;


        /// <summary>
        /// 验证码类的构造函数
        /// </summary>
        /// <param name="imageWidth">验证码图片的长度</param>
        /// <param name="imageHeight">验证码图片的高度</param>
        /// <param name="codeLength">验证码字符串的长度</param>
        /// <param name="emSize">新字体的全身大小</param>
        public ValidateCode(int imageWidth, int imageHeight, int codeLength, float emSize)
        {
            _imageWidth = imageWidth;
            _imageHeight = imageHeight;
            _codeLength = codeLength;
            _emSize = emSize;
        }

        /// <summary>
        /// 新字体的全身大小
        /// </summary>
        public float EmSize
        {
            get
            {
                return _emSize;
            }
        }

        /// <summary>
        /// 验证码图片的长度
        /// </summary>
        public int ImageWidth
        {
            get
            {
                return _imageWidth;
            }
        }

        /// <summary>
        /// 验证码图片的高度
        /// </summary>
        public int ImageHeight
        {
            get
            {
                return _imageHeight;
            }
        }

        /// <summary>
        /// 验证码字符串的长度
        /// </summary>
        public int CodeLength
        {
            get
            {
                return _codeLength;
            }
        }

        /// <summary>
        /// 验证码数组
        /// </summary>
        public String[] ValidateCodes
        {
            get
            {
                return _validateCodes;
            }
        }

        /// <summary>
        /// 生成验证码字符串
        /// </summary>
        /// <returns></returns>
        private string CreateValidateString()
        {
            string validateStr = "";

            string[] validateCodes = new string[_codeLength];

            //生成起始序列值
            int seekSeek = unchecked((int)DateTime.Now.Ticks);
            Random seekRand = new Random(seekSeek);
            int beginSeek = (int)seekRand.Next(0, Int32.MaxValue - _codeLength * 10000);
            int[] seeks = new int[_codeLength];

            for (int i = 0; i < _codeLength; i++)
            {
                beginSeek += 10000;
                seeks[i] = beginSeek;
            }

            for (int i = 0; i < _codeLength; i++)
            {
                Random rnd = new Random(seeks[i]);

                int index = rnd.Next(0, _fullCodes.Length);

                validateCodes[i] = _fullCodes[index];
            }

            for (int i = 0; i < _codeLength; i++)
            {
                validateStr += validateCodes[i].ToString() + " ";
            }

            _validateCodes = validateCodes;

            return validateStr;

        }

        /// <summary>
        /// 输出验证码图片
        /// </summary>
        /// <param name="containsPage">要输出到的page对象</param>
        public void CreateValidateGraphic(Page containsPage)
        {
            string validateStr = CreateValidateString();

            //Bitmap image = new Bitmap((int)Math.Ceiling(validateNum.Length * 12.5), 22);
            Bitmap image = new Bitmap(_imageWidth, _imageHeight);

            Graphics g = Graphics.FromImage(image);

            try
            {
                //生成随机生成器
                Random random = new Random();

                //清空图片背景色
                g.Clear(Color.White);

                //画图片的干扰线
                //for (int i = 0; i < 25; i++)
                //{
                //    int x1 = random.Next(image.Width);
                //    int x2 = random.Next(image.Width);
                //    int y1 = random.Next(image.Height);
                //    int y2 = random.Next(image.Height);
                //    g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2);
                //}

                //Font font = new Font("Arial", 12, (FontStyle.Bold | FontStyle.Italic));
                //Font font = new Font("Comic Sans MS", 18, (FontStyle.Bold | FontStyle.Italic));
                Font font = new Font("Comic Sans MS", _emSize, (FontStyle.Bold));//| FontStyle.Italic

                //LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Blue, Color.DarkRed, 1.2f, true);
                LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.FromArgb(126, 190, 202), Color.FromArgb(126, 190, 202), 1.2f, true);
                
                //g.DrawString(validateNum, font, brush, 3, 2);
                g.DrawString(validateStr, font, brush, 5, 2);

                //画图片的前景干扰点
                //for (int i = 0; i < 100; i++)
                //{
                //    int x = random.Next(image.Width);
                //    int y = random.Next(image.Height);
                //    image.SetPixel(x, y, Color.FromArgb(random.Next()));
                //}

                //画图片的边框线
                g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);

                //保存图片数据
                MemoryStream stream = new MemoryStream();
                image.Save(stream, ImageFormat.Jpeg);

                //输出图片
                containsPage.Response.Clear();
                containsPage.Response.ContentType = "image/jpeg";
                containsPage.Response.BinaryWrite(stream.ToArray());

            }
            finally
            {
                g.Dispose();
                image.Dispose();
            }

        }

 
    }

 
}