天天看点

.net实现验证码功能 - 飛雪飄寒

  验证码功能一般是用于防止批量注册的,不少网站为了防止用户利用机器人自动注册、登录、灌水,都采用了验证码技术。所谓验证码,就是将一串随机产生的数字或字母或符号或文字,生成一幅图片, 图片里加上一些干扰象素(防止OCR),由用户肉眼识别其中的验证码信息,输入表单提交网站验证,验证成功后才能使用某项功能。

  一、验证码简介

  验证码功能一般是用于防止批量注册的,不少网站为了防止用户利用机器人自动注册、登录、灌水,都采用了验证码技术。所谓验证码,就是将一串随机产生的数字或字母或符号或文字,生成一幅图片, 图片里加上一些干扰象素(防止OCR),由用户肉眼识别其中的验证码信息,输入表单提交网站验证,验证成功后才能使用某项功能。

  常见的验证码有如下几种: 

  1、纯数字验证码,一般为四位随机数字;

  2、数字+字母验证码,一般从数字(0~9)和字母(A~Z和a~z)中随机抽出几个字符组成;

  3、汉字验证码,相对而言,这种验证码比较少见一点,实现起来也相对复杂一些,但在不少网站中还是可以看到的;

  二、验证码的实现

  1、纯数字验证码的实现

  纯数字验证码的实现相对比较简单,可通过以下两种方法来实现

  (1)使用随机数方式,代码如下: 

        private String GetRandomint(int codeCount)

        {

            Random random = new Random();

            string min = "";

            string max = "";

            for (int i = 0; i < codeCount; i++)

            {

                min +="1";

                max+="9";

            }

                return (random.Next(Convert.ToInt32(min),Convert.ToInt32(max)).ToString());

        }

   (2)使用随机组合方式,代码如下:

        private string CreateRandomCode(int codeCount)

        {

            string allChar = "0,1,2,3,4,5,6,7,8,9"; 

            string[] allCharArray = allChar.Split(\',\'); 

            string randomCode = ""; 

            int temp = -1; 

            Random rand = new Random(); 

            for (int i = 0; i < codeCount; i++) 

            { 

                if (temp != -1) 

                { 

                    rand = new Random(i * temp * ((int)DateTime.Now.Ticks)); 

                } 

                int t = rand.Next(9); 

                if (temp == t) 

                { 

                    return CreateRandomCode(codeCount); 

                } 

                temp = t; 

                randomCode += allCharArray[t]; 

            } 

            return randomCode;

        }

  2、数字+字母验证码的实现,代码如下:

        private string CreateRandomCode(int codeCount)

        {

            string allChar = "0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,W,X,Y,Z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"; 

            string[] allCharArray = allChar.Split(\',\'); 

            string randomCode = ""; 

            int temp = -1; 

            Random rand = new Random(); 

            for (int i = 0; i < codeCount; i++) 

            { 

                if (temp != -1) 

                { 

                    rand = new Random(i * temp * ((int)DateTime.Now.Ticks)); 

                } 

                int t = rand.Next(61); 

                if (temp == t) 

                { 

                    return CreateRandomCode(codeCount); 

                } 

                temp = t; 

                randomCode += allCharArray[t]; 

            } 

            return randomCode;

        }

  3、汉字验证码的实现,代码如下: 

        /**/

        /* 

    此函数在汉字编码范围内随机创建含两个元素的十六进制字节数组,每个字节数组代表一个汉字,并将 

    四个字节数组存储在object数组中。 

    参数:strlength,代表需要产生的汉字个数 

    */

        public static object[] CreateRegionCode(int strlength)

        {

            //定义一个字符串数组储存汉字编码的组成元素 

            string[] rBase = new String[16] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };

            Random rnd = new Random();

            //定义一个object数组用来 

            object[] bytes = new object[strlength];

            /**/

            /*每循环一次产生一个含两个元素的十六进制字节数组,并将其放入bject数组中 

         每个汉字有四个区位码组成 

         区位码第1位和区位码第2位作为字节数组第一个元素 

         区位码第3位和区位码第4位作为字节数组第二个元素 

        */

            for (int i = 0; i < strlength; i++)

            {

                //区位码第1位 

                int r1 = rnd.Next(11, 14);

                string str_r1 = rBase[r1].Trim();

                //区位码第2位 

                rnd = new Random(r1 * unchecked((int)DateTime.Now.Ticks) + i);//更换随机数发生器的种子避免产生重复值 

                int r2;

                if (r1 == 13)

                {

                    r2 = rnd.Next(0, 7);

                }

                else

                {

                    r2 = rnd.Next(0, 16);

                }

                string str_r2 = rBase[r2].Trim();

                //区位码第3位 

                rnd = new Random(r2 * unchecked((int)DateTime.Now.Ticks) + i);

                int r3 = rnd.Next(10, 16);

                string str_r3 = rBase[r3].Trim();

                //区位码第4位 

                rnd = new Random(r3 * unchecked((int)DateTime.Now.Ticks) + i);

                int r4;

                if (r3 == 10)

                {

                    r4 = rnd.Next(1, 16);

                }

                else if (r3 == 15)

                {

                    r4 = rnd.Next(0, 15);

                }

                else

                {

                    r4 = rnd.Next(0, 16);

                }

                string str_r4 = rBase[r4].Trim();

                //定义两个字节变量存储产生的随机汉字区位码 

                byte byte1 = Convert.ToByte(str_r1 + str_r2, 16);

                byte byte2 = Convert.ToByte(str_r3 + str_r4, 16);

                //将两个字节变量存储在字节数组中 

                byte[] str_r = new byte[] { byte1, byte2 };

                //将产生的一个汉字的字节数组放入object数组中 

                bytes.SetValue(str_r, i);

            }

            return bytes;

        }

  三、具体实例 

  (实例1) 

前台代码display.aspx

<body>

    <form id="form1" runat="server">

    <div>

       <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>

        <asp:Image ID="Image1" runat="server" ImageUrl="png.aspx" /><br />

        <br />

       <asp:Button ID="Button2" runat="server" OnClick="Button2_Click" Text="Button" />

        <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="True" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">

            <asp:ListItem Value="3">默认</asp:ListItem>

            <asp:ListItem Value="1">文字</asp:ListItem>

            <asp:ListItem Value="2">数字</asp:ListItem>

            <asp:ListItem Value="3">混合</asp:ListItem>

        </asp:DropDownList></div>

    </form>

</body>

后台代码display.cs

        protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)

        {

            switch (DropDownList1.SelectedValue)

            {

                case "1":

                    Image1.ImageUrl = "png.aspx?aa=1";

                    break;

                case "2":

                    Image1.ImageUrl = "png.aspx?aa=2";

                    break;

                case "3":

                    Image1.ImageUrl = "png.aspx?aa=3";

                    break;

            }

        }

        protected void Button2_Click(object sender, EventArgs e)

        {

            if (TextBox1.Text == Session["gif"].ToString())

                Response.Write("OK,正确");

            else

                Response.Write("验证码不符合");

        }

后台代码png.cs

    public partial class png : System.Web.UI.Page

    {         

        protected void Page_Load(object sender, EventArgs e)

        {

            switch (Request.QueryString["aa"])

            {

                case "1":

                    gif = stxt(10);

                    Session["gif"] = stxt(10);

                    break;

                case "2":

                    gif = GetRandomint(4);

                    Session["gif"] = GetRandomint(4);

                    break;

                case "3":

                    gif = CreateRandomCode(4);

                    Session["gif"] = CreateRandomCode(4);

                    break;

                default:

                    gif = CreateRandomCode(4);

                    Session["gif"] = CreateRandomCode(4);

                    break;

            }

            CreateImage(Session["gif"].ToString());

        }

        private String GetRandomint(int codeCount)

        {

            Random random = new Random();

            string min = "";

            string max = "";

            for (int i = 0; i < codeCount; i++)

            {

                min +="1";

                max+="9";

            }

                return (random.Next(Convert.ToInt32(min),Convert.ToInt32(max)).ToString());

        }

        /**/

        /* 

    此函数在汉字编码范围内随机创建含两个元素的十六进制字节数组,每个字节数组代表一个汉字,并将 

    四个字节数组存储在object数组中。 

    参数:strlength,代表需要产生的汉字个数 

    */

        public static object[] CreateRegionCode(int strlength)

        {

            //定义一个字符串数组储存汉字编码的组成元素 

            string[] rBase = new String[16] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };

            Random rnd = new Random();

            //定义一个object数组用来 

            object[] bytes = new object[strlength];

            /**/

            /*每循环一次产生一个含两个元素的十六进制字节数组,并将其放入bject数组中 

         每个汉字有四个区位码组成 

         区位码第1位和区位码第2位作为字节数组第一个元素 

         区位码第3位和区位码第4位作为字节数组第二个元素 

        */

            for (int i = 0; i < strlength; i++)

            {

                //区位码第1位 

                int r1 = rnd.Next(11, 14);

                string str_r1 = rBase[r1].Trim();

                //区位码第2位 

                rnd = new Random(r1 * unchecked((int)DateTime.Now.Ticks) + i);//更换随机数发生器的种子避免产生重复值 

                int r2;

                if (r1 == 13)

                {

                    r2 = rnd.Next(0, 7);

                }

                else

                {

                    r2 = rnd.Next(0, 16);

                }

                string str_r2 = rBase[r2].Trim();

                //区位码第3位 

                rnd = new Random(r2 * unchecked((int)DateTime.Now.Ticks) + i);

                int r3 = rnd.Next(10, 16);

                string str_r3 = rBase[r3].Trim();

                //区位码第4位 

                rnd = new Random(r3 * unchecked((int)DateTime.Now.Ticks) + i);

                int r4;

                if (r3 == 10)

                {

                    r4 = rnd.Next(1, 16);

                }

                else if (r3 == 15)

                {

                    r4 = rnd.Next(0, 15);

                }

                else

                {

                    r4 = rnd.Next(0, 16);

                }

                string str_r4 = rBase[r4].Trim();

                //定义两个字节变量存储产生的随机汉字区位码 

                byte byte1 = Convert.ToByte(str_r1 + str_r2, 16);

                byte byte2 = Convert.ToByte(str_r3 + str_r4, 16);

                //将两个字节变量存储在字节数组中 

                byte[] str_r = new byte[] { byte1, byte2 };

                //将产生的一个汉字的字节数组放入object数组中 

                bytes.SetValue(str_r, i);

            }

            return bytes;

        }

        private string stxt(int num)

        {

            Encoding gb = Encoding.GetEncoding("gb2312");

            //调用函数产生10个随机中文汉字编码 

            object[] bytes = CreateRegionCode(num);

            string strtxt = "";

            //根据汉字编码的字节数组解码出中文汉字 

            for (int i = 0; i < num; i++)

            {

                strtxt += gb.GetString((byte[])Convert.ChangeType(bytes[i], typeof(byte[])));

            }

            return strtxt;

        }

        /// <summary>

        /// 这个是使用字母,数字混合

        /// </summary>

        /// <param name="VcodeNum"></param>

        /// <returns></returns>

        private string CreateRandomCode(int codeCount)

        {

            string allChar = "0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,W,X,Y,Z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z";

            string[] allCharArray = allChar.Split(\',\');

            string randomCode = "";

            int temp = -1;

            Random rand = new Random();

            for (int i = 0; i < codeCount; i++)

            {

                if (temp != -1)

                {

                    rand = new Random(i * temp * ((int)DateTime.Now.Ticks));

                }

                int t = rand.Next(61);

                if (temp == t)

                {

                    return CreateRandomCode(codeCount);

                }

                temp = t;

                randomCode += allCharArray[t];

            }

            return randomCode;

        }

        private void CreateImage(string checkCode)

        {

            int iwidth = (int)(checkCode.Length * 20);

            System.Drawing.Bitmap image = new System.Drawing.Bitmap(iwidth, 25);

            Graphics g = Graphics.FromImage(image);

            Font f = new System.Drawing.Font("Arial", 10, System.Drawing.FontStyle.Bold);

            Brush b = new System.Drawing.SolidBrush(Color.White);

            //g.FillRectangle(new System.Drawing.SolidBrush(Color.Blue),0,0,image.Width, image.Height);    

            g.Clear(Color.Black);

            g.DrawString(checkCode, f, b, 3, 3);

            Pen blackPen = new Pen(Color.Black, 0);

            Random rand = new Random();

            //for (int i=0;i<5;i++)    

            //{        

            //    int y = rand.Next(image.Height);  

            //    g.DrawLine(blackPen,0,y,image.W

idth,y); 

            //}        

            System.IO.MemoryStream ms = new System.IO.MemoryStream();

            image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);

            Response.ClearContent();

            Response.ContentType = "image/Jpeg";

            Response.BinaryWrite(ms.ToArray());

            g.Dispose();

            image.Dispose();

        }

    }

  (实例2):20101018续加

调用页面前台代码

        <script language="Javascript">

        function Regist()

        {

            var url = "";

            url = "/GZPI/Service/Registry/ViewProtocol.aspx";

            window.open(url);    

            return false;

        }

        function LoginClick()

        {

            if(document.Login.UserName.value == "")

            {

                alert("用户名不能为空!");

                return false;

            }

            document.Login.submit();

            document.Login.Password.value = "";

            return false;

        }

        function f_refreshtype()

        {    

            var Image1 = document.getElementById("IMGCheckCode");

              if (Image1 != null) 

               {

                   Image1.src = Image1.src + "?";

             }

        }        

        </script>

                        <TABLE cellSpacing="0" cellPadding="5" width="100%" border="0">

                            <TR>

                                <TD class="fontblack" align="right" width="30%">用 户 名:</TD>

                                <TD vAlign="bottom" align="left" width="62%"><input id="Text1" style="BORDER-RIGHT: #43a7e2 1px solid; BORDER-TOP: #43a7e2 1px solid; BACKGROUND: #fcfcfc; BORDER-LEFT: #43a7e2 1px solid; BORDER-BOTTOM: #43a7e2 1px solid"

                                        size="13" name="UserName" width="100px">

                                </TD>

                            </TR>

                            <TR>

                                <TD class="fontblack" align="right" height="23">密 &nbsp;&nbsp;&nbsp;码:</TD>

                                <TD vAlign="bottom" align="left" height="23"><input id="Password1" style="BORDER-RIGHT: #43a7e2 1px solid; BORDER-TOP: #43a7e2 1px solid; BACKGROUND: #fcfcfc; BORDER-LEFT: #43a7e2 1px solid; BORDER-BOTTOM: #43a7e2 1px solid"

                                        type="password" size="13" name="Password" width="100px">

                                </TD>

                            </TR>

                            <TR>

                                <TD class="fontblack" align="right" height="23">校&nbsp;验 码:</TD>

                                <TD valign="top" align="left" height="23"><FONT face="宋体"><INPUT id="CheckCode" style="BORDER-RIGHT: #43a7e2 1px solid; BORDER-TOP: #43a7e2 1px solid; BACKGROUND: #fcfcfc; BORDER-LEFT: #43a7e2 1px solid; BORDER-BOTTOM: #43a7e2 1px solid"

                                            width="100px" size="13" name="CheckCode">&nbsp;</FONT><a style="CURSOR: hand" onclick="f_refreshtype()" title="看不清楚?点击获取新的校验码!" border="0"><IMG id="IMGCheckCode" src="../GenerateCheckCode.aspx"></a>

                                </TD>

                            </TR>

                            <TR vAlign="bottom" align="center">

                                <TD class="dlbuttom" colSpan="2" height="23"><input id="Image1" style="CURSOR: hand" onclick="return LoginClick();" tabIndex="3" type="image"

                                        height="17" width="55" src="images/login.gif" border="0" name="OkButton">&nbsp;&nbsp;&nbsp;

                                    <input type="image" onClick="return Regist();" border=\'0\' src=\'images/zuce.gif\' width=\'55\'

                                        height=\'17\' ID="Image2" NAME="Image2">

                                </TD>

                            </TR>

                        </TABLE>

调用页面后台代码

    private void OK_Click(object sender, System.EventArgs e)

        {

            if (!CheckCodeSame(CheckCode.Text.Trim()))

            {                    

                System.Web.HttpContext.Current.Response.Write("<Script Language=\'JavaScript\'>window.alert(\'校验码错误!请重新输入!\');window.close();</script>");

                return;

            }        

            int userType = 1;

            try

            {

                userType = int.Parse(UserType.Text);

            }

            catch

            {

            }

            GatewayManager gateway = new GatewayManager(corpCode.Text,collegeCode.Text,chargeCode.Text,userName.Text,password.Text,userType);

            gateway.Login(this);

        }

        /// <summary>

        /// 判断输入的校验码是否正确

        /// </summary>

        /// <param name="checkCode"></param>

        /// <returns></returns>

        public static bool CheckCodeSame(string checkCode)

        {

            bool bSame = false; ;

            if (HttpContext.Current.Session["CheckCode"] != null)

            {

                if (checkCode.ToUpper() == HttpContext.Current.Session["CheckCode"].ToString().ToUpper())

                {

                    bSame = true;

                }

            }

            return bSame;

        }

  

生成验证码前台文件

<HTML>

    <HEAD>

        <title>GenerateCheckCode</title>

        <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">

        <meta name="CODE_LANGUAGE" Content="C#">

        <meta name="vs_defaultClientScript" content="JavaScript">

        <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">

    </HEAD>

    <body>

        <form id="form1" runat="server">

            <div><FONT face="宋体"></FONT>

            </div>

        </form>

    </body>

</HTML>

生成验证码后台文件

using System;

using System.Collections;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Drawing;

using System.Drawing.Drawing2D;

namespace GZPI.Gateway

{

    /// <summary>

    /// GenerateCheckCode 的摘要说明。

    /// </summary>

    public class GenerateCheckCode : System.Web.UI.Page

    {

        private void Page_Load(object sender, System.EventArgs e)

        {

            // 在此处放置用户代码以初始化页面

            this.CreateCheckCodeImage(GenerateCheckCodes(4));

        }

        #region Web 窗体设计器生成的代码

        override protected void OnInit(EventArgs e)

        {

            //

            // CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。

            //

            InitializeComponent();

            base.OnInit(e);

        }

        /// <summary>

        /// 设计器支持所需的方法 - 不要使用代码编辑器修改

        /// 此方法的内容。

        /// </summary>

        private void InitializeComponent()

        {    

            this.Load += new System.EventHandler(this.Page_Load);

        }

        #endregion

        private string GenerateCheckCodes(int iCount)

        {

            int number;

            string checkCode = String.Empty;

            int iSeed = DateTime.Now.Millisecond;

            System.Random random = new Random(iSeed);

            for (int i = 0; i < iCount; i++)

            {

                number = random.Next(10);

                checkCode += number.ToString();

            }

            Session["CheckCode"] = checkCode;

            return checkCode;

        }

        private void CreateCheckCodeImage(string checkCode)

        {

            if (checkCode == null || checkCode.Trim() == String.Empty)

                return;

            int iWordWidth = 15;

            int iImageWidth = checkCode.Length * iWordWidth;

            Bitmap image = new Bitmap(iImageWidth, 20);

            Graphics g = Graphics.FromImage(image);

            try

            {

                //生成随机生成器 

                Random random = new Random();

                //清空图片背景色 

                g.Clear(Color.White);

                //画图片的背景噪音点

                for (int i = 0; i < 20; 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);

                }

                //画图片的背景噪音线 

                for (int i = 0; i < 2; i++)

                {

                    int x1 = 0;

                    int x2 = image.Width;

                    int y1 = random.Next(image.Height);

                    int y2 = random.Next(image.Height);

                    if (i == 0)

                    {

                        g.DrawLine(new Pen(Color.Gray, 2), x1, y1, x2, y2);

                    }

                }

                for (int i = 0; i < checkCode.Length; i++)

                {

                    string Code = checkCode[i].ToString();

                    int xLeft = iWordWidth * (i);

                    random = new Random(xLeft);

                    int iSeed = DateTime.Now.Millisecond;

                    int iValue = random.Next(iSeed) % 4;

                    if (iValue == 0)

                    {

                        Font font = new Font("Arial", 13, (FontStyle.Bold | System.Drawing.FontStyle.Italic));

                        Rectangle rc = new Rectangle(xLeft, 0, iWordWidth, image.Height);

                        LinearGradientBrush brush = new LinearGradientBrush(rc, Color.Blue, Color.Red, 1.5f, true);

                        g.DrawString(Code, font, brush, xLeft, 2);

                    }

                    else if (iValue == 1)

                    {

                        Font font = new System.Drawing.Font("楷体", 13, (FontStyle.Bold));

                        Rectangle rc = new Rectangle(xLeft, 0, iWordWidth, image.Height);

                        LinearGradientBrush brush = new LinearGradientBrush(rc, Color.Blue, Color.DarkRed, 1.3f, true);

                        g.DrawString(Code, font, brush, xLeft, 2);

                    }

                    else if (iValue == 2)

                    {

                        Font font = new System.Drawing.Font("宋体", 13, (System.Drawing.FontStyle.Bold));

                        Rectangle rc = new Rectangle(xLeft, 0, iWordWidth, image.Height);

                        LinearGradientBrush brush = new LinearGradientBrush(rc, Color.Green, Color.Blue, 1.2f, true);

                        g.DrawString(Code, font, brush, xLeft, 2);

                    }

                    else if (iValue == 3)

                    {

                        Font font = new System.Drawing.Font("黑体", 13, (System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Bold));

                        Rectangle rc = new Rectangle(xLeft, 0, iWordWidth, image.Height);

                        LinearGradientBrush brush = new LinearGradientBrush(rc, Color.Blue, Color.Green, 1.8f, true);

                        g.DrawString(Code, font, brush, xLeft, 2);

                    }

                }

                //////画图片的前景噪音点 

                //for (int i = 0; i < 8; 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);

                System.IO.MemoryStream ms = new System.IO.MemoryStream();

                image.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);

                Response.ClearContent();

                Response.BinaryWrite(ms.ToArray());

            }

            finally

            {

                g.Dispose();

                image.Dispose();

            }

        }

    }

}

  四、效果图展示

  验证码数字

.net实现验证码功能 - 飛雪飄寒

  验证码数字+字母

.net实现验证码功能 - 飛雪飄寒

  验证码汉字

.net实现验证码功能 - 飛雪飄寒
.net实现验证码功能 - 飛雪飄寒