C# 验证码的一种实现

来源:互联网 发布:mysql 视图查询效率 编辑:程序博客网 时间:2024/06/02 19:28

测试了下小功能验证码的实现

下面的简略效果


代码目录结构



default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TestCode._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>        <script language="javascript" type="text/javascript">       function CheckAccount()      {          var imagecode = document.getElementById("TextBoxImageCode");           var img = document.getElementById("imgCode");                     if(imagecode.value.length == 0)          {              alert("验证码不能为空!");              img.src = "GetImageCode.aspx?r=" + Math.random();               imagecode.value='';              return false;           }          }             </script></head><body>    <form id="form1" runat="server">    <div>        <asp:TextBox ID="TextBoxImageCode" runat="server" TabIndex="2" MaxLength="6" autocomplete="off"></asp:TextBox>        <br />        <img id="imgCode" runat="server" width="150" height="20" />        <br />        <asp:Button ID="ButtonOK" runat="server"  OnClick="ButtonOK_Click" OnClientClick="return CheckAccount()" Width="100" Height="30" Text="验证"/>                <br />        <asp:Label ID="lblMessage" runat="server" Text=""></asp:Label>            </div>    </form></body></html>


default.aspx.cs

using System;using System.Collections;using System.Configuration;using System.Data;using System.Linq;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.HtmlControls;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Xml.Linq;namespace TestCode{    public partial class _Default : System.Web.UI.Page    {        protected void Page_Load(object sender, EventArgs e)        {            InitImageCode();        }        private void InitImageCode()        {            this.imgCode.Src = "~/GetImageCode.aspx?r=" + new Random().Next();        }        protected void ButtonOK_Click(object sender, EventArgs e)        {            string code = TextBoxImageCode.Text.Trim();            if (CheckImageCode(code))            {                lblMessage.Text = "验证通过";            }            else            {                lblMessage.Text = "验证不通过";            }            TextBoxImageCode.Text = string.Empty;        }        /// <summary>        /// 检查图片验证码是否正确        /// </summary>        /// <returns></returns>        private bool CheckImageCode(string code)        {            if (code.ToUpper() == SessionManager.ImageCode.ToUpper())            {                return true;            }            else            {                //this.Alert("Image code输入错误,请重新输入。");                return false;            }        }    }}


SessionManager.cs
using System;using System.Data;using System.Collections.Generic;using System.Configuration;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;namespace TestCode{    public sealed class SessionManager    {        #region 定义系统中所有Session的Key值,以常量方式提供        private const string IMAGECODE = "ImageCode";        /// <summary>        /// 图形验证码        /// </summary>        public static string ImageCode        {            get            {                return HttpContext.Current.Session[IMAGECODE] == null ? "Get image code error" :                       HttpContext.Current.Session[IMAGECODE].ToString();            }            set            {                HttpContext.Current.Session[IMAGECODE] = value;            }        }        #endregion    }


用于返回图形验证码图片

using System;using System.Data;using System.Configuration;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 System.Web.SessionState;using System.Drawing;namespace TestCode{    /// <summary>    /// 用于返回图形验证码图片    /// </summary>    public class GetImageCode : IHttpHandler, IRequiresSessionState    {        /// <summary>        /// HttpHandler成员方法        /// </summary>          public void ProcessRequest(HttpContext ctx)        {            string imageCodeKey = "";            byte[] data = GenerateVerifyImage(6, ref imageCodeKey, true, false);            SessionManager.ImageCode = imageCodeKey;            ctx.Response.OutputStream.Write(data, 0, data.Length);        }        /// <summary>        /// HttpHandler成员属性        /// </summary>        public bool IsReusable        {            get            {                return true;            }        }        /// <summary>        /// 生成图片验证码        /// </summary>        /// <param name="nLen">验证码的长度</param>        /// <param name="strKey">输出参数,验证码的内容</param>        /// <param name="PureBlackBackGround">是否黑白色</param>        /// <returns>图片字节流</returns>               private byte[] GenerateVerifyImage(int keyLength,                                            ref string imageCodeKey,                                            bool pureBlackBackGround,                                            bool drawDisturbLine)        {            int bmpWidth = 26 * keyLength + 8;            int bmpHeight = 20;            System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(bmpWidth, bmpHeight);            // 1. 生成随机背景颜色            int red, green, blue;  // 背景的三元色            System.Random rd = new Random((int)System.DateTime.Now.Ticks);            if (!pureBlackBackGround)            {                red = rd.Next(255) % 128 + 128;                green = rd.Next(255) % 128 + 128;                blue = rd.Next(255) % 128 + 128;            }            else            {                red = 255;                green = 255;                blue = 255;            }            // 2. 填充位图背景            System.Drawing.Graphics graph = System.Drawing.Graphics.FromImage(bmp);            graph.FillRectangle(new SolidBrush(System.Drawing.Color.FromArgb(red, green, blue))             , 0             , 0             , bmpWidth             , bmpHeight);            // 3. 绘制干扰线条,采用比背景略深一些的颜色            if (drawDisturbLine)            {                int lines = 3;                System.Drawing.Pen pen;                if (!pureBlackBackGround)                {                    pen = new System.Drawing.Pen(System.Drawing.Color.FromArgb(red - 17, green - 17, blue - 17), 1);                }                else                {                    pen = new System.Drawing.Pen(System.Drawing.Color.FromArgb(12, 12, 12), 1);                }                for (int a = 0; a < lines; a++)                {                    int x1 = rd.Next() % bmpWidth;                    int y1 = rd.Next() % bmpHeight;                    int x2 = rd.Next() % bmpWidth;                    int y2 = rd.Next() % bmpHeight;                    graph.DrawLine(pen, x1, y1, x2, y2);                }            }            // 采用的字符集,可以随即拓展,并可以控制字符出现的几率            string codeScop = "ABCDEFGHJKLMNPRSTUVWXYZ23456789";            // 4. 循环取得字符,并绘制            string result = "";            for (int i = 0; i < keyLength; i++)            {                int coordinateX = (i * 26 + rd.Next(3));                int coordinateY = rd.Next(2) + 1;                // 确定字体                System.Drawing.Font font = new System.Drawing.Font("Courier New",                 13 + rd.Next() % 4,                 System.Drawing.FontStyle.Bold);                char currentChar = codeScop[rd.Next(codeScop.Length)];  // 随机获取字符                result += currentChar.ToString();                // 绘制字符                if (!pureBlackBackGround)                {                    graph.DrawString(currentChar.ToString(),                     font,                     new SolidBrush(System.Drawing.Color.FromArgb(red - 60 + coordinateY * 3,                     green - 60 + coordinateY * 3,                     blue - 40 + coordinateY * 3)),                     coordinateX,                     coordinateY);                }                else                {                    graph.DrawString(currentChar.ToString(),                    font,                    new SolidBrush(System.Drawing.Color.FromArgb(0, 0, 0)),                    coordinateX,                    coordinateY);                }            }            // 5. 输出字节流            System.IO.MemoryStream bstream = new System.IO.MemoryStream();            //bmp = TwistImage(bmp, true, 2.0, 2.0);            bmp.Save(bstream, System.Drawing.Imaging.ImageFormat.Jpeg);            bmp.Dispose();            graph.Dispose();            imageCodeKey = result;            byte[] byteReturn = bstream.ToArray();            bstream.Close();            return byteReturn;        }        private const double PI = 3.1415926535897932384626433832795;        private const double DOUBLE_PI = 6.283185307179586476925286766559;        /// <summary>        /// 正弦曲线Wave扭曲图片        /// </summary>        /// <param name="srcBmp">源图片</param>        /// <param name="bXDir">是否横向</param>        /// <param name="nMultValue">波形的幅度倍数</param>        /// <param name="dPhase">波形的起始相位,取值区间[0-2*PI)</param>        /// <returns></returns>        public System.Drawing.Bitmap TwistImage(Bitmap srcBmp, bool bXDir, double dMultValue, double dPhase)        {            System.Drawing.Bitmap destBmp = new Bitmap(srcBmp.Width, srcBmp.Height);            // 将位图背景填充为白色            System.Drawing.Graphics graph = System.Drawing.Graphics.FromImage(destBmp);            graph.FillRectangle(new SolidBrush(System.Drawing.Color.White), 0, 0, destBmp.Width, destBmp.Height);            graph.Dispose();            double dBaseAxisLen = bXDir ? (double)destBmp.Height : (double)destBmp.Width;            for (int i = 0; i < destBmp.Width; i++)            {                for (int j = 0; j < destBmp.Height; j++)                {                    double dx = 0;                    dx = bXDir ? (DOUBLE_PI * (double)j) / dBaseAxisLen : (DOUBLE_PI * (double)i) / dBaseAxisLen;                    dx += dPhase;                    double dy = Math.Sin(dx);                    // 取得当前点的颜色                    int nOldX = 0, nOldY = 0;                    nOldX = bXDir ? i + (int)(dy * dMultValue) : i;                    nOldY = bXDir ? j : j + (int)(dy * dMultValue);                    System.Drawing.Color color = srcBmp.GetPixel(i, j);                    if (nOldX >= 0 && nOldX < destBmp.Width                     && nOldY >= 0 && nOldY < destBmp.Height)                    {                        destBmp.SetPixel(nOldX, nOldY, color);                    }                }            }            return destBmp;        }    }}


web.config


<httpHandlers>
        <add verb="*" path="GetImageCode.aspx" type="TestCode.GetImageCode,TestCode"/>

        </httpHandlers>