主题:  ASP.NET中如何动态生成图形验证码

蓝鲸

职务:版主
等级:5
金币:42.1
发贴:2614
#12004/11/28 19:31:25
近来练习做个文章发布系统,感觉用.NET在有些方面确实很方便。其中有个小功能就是身份验证时的验证码产生问题,吸取allinhands斑竹等建议,采用图片输出验证码。吸取了过去ASP中的一些方法,避开了ASP产生图片的复杂性,使用.NET的GDI+动态生成图片的方法。

对于身份验证,.NET有一套方法,我正在学习,由于时间问题,还没实践。本方法是一小技巧,你可以把它看成是一个动态图片生成的小技巧。如果你GDI+学得好,可以输出很漂亮的曲线图或CHAT图形等。

验证的页面如下,验证的代码我不写了,相信大家都很熟悉。只是有一要点需要提一下,使用一Image控件,并设置ImageUrl属性为"inc/CheckCode.aspx",CheckCode.aspx是专门负责产生图片和生成验证码Session的。


图片如下:


另在Page_Load事件中,加以下代码:

// 检验验证码是否正确
if ( Session["AdminCheckCode"] == null)
{
    labInfo.Text = "输入验证码不正确,请重新输入。";
    imgCheckCode.ImageUrl = "../inc/CheckCode.aspx";
    return;
}
if (txtCheckCode.Text != Session["AdminCheckCode"].ToString())
{
    labInfo.Text = "输入验证码不正确,请重新输入。";
    imgCheckCode.ImageUrl = "../inc/CheckCode.aspx";
    return;
}

CheckCode.aspx代码为:
        private void Page_Load(object sender, System.EventArgs e)
        {
            string strCode = RndCode();
            Session["AdminCheckCode"] = strCode;

            int width = 35;
            int height = 16;
            Bitmap bmp = new Bitmap(width, height);
            Graphics g = Graphics.FromImage(bmp);

            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.Clear(Color.White);            
            g.DrawString(strCode, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new Point(0, 0));
            
            bmp.Save(Response.OutputStream, ImageFormat.Gif);

            g.Dispose();
            bmp.Dispose();
        }

        // 产生随机数函数
        private string RndCode()
        {
            Random rnd = new Random();
            int intRnd = 0;

            while (intRnd < 1000)
            {
                 intRnd = rnd.Next(10000);
            }

            return intRnd.ToString();
        }


非常大鱼

缺缺

职务:管理员
等级:8
金币:41.0
发贴:9620
#22004/11/28 23:05:54
从理论上来说,图片的越复杂安全性越高,比如加一个乱七八糟的噪点,不同的颜色,不同的字体.当然,一般情况下我们也没有必要去搞那种那复杂的图片.
不过,我们可以把图片做的好看一点..

先看示例:

图片如下:



缺缺

职务:管理员
等级:8
金币:41.0
发贴:9620
#32004/11/28 23:08:08
		private void CreateImage(string checkCode)
		{
			int iwidth = (int)(checkCode.Length * 15);
			System.Drawing.Bitmap image = new System.Drawing.Bitmap(iwidth, 25);
			Graphics g = Graphics.FromImage(image);
			g.Clear(Color.White);
//定义颜色
			Color[] c = {Color.Black,Color.Red,Color.DarkBlue,Color.Green,Color.Orange,Color.Brown,Color.DarkCyan,Color.Purple};
//定义字体			string[] font = {"Verdana","Microsoft Sans Serif","Comic Sans MS","Arial","宋体"};
			Random rand = new Random();
//随机输出噪点
			for(int i=0;i<50;i++)
			{
				int x = rand.Next(image.Width);
				int y = rand.Next(image.Height);
				g.DrawRectangle(new Pen(Color.LightGray, 0),x,y,1,1);
			}

//输出不同字体和颜色的验证码字符
			for(int i=0;i<checkCode.Length;i++)
			{
				int cindex = rand.Next(7);
				int findex = rand.Next(5);
				
				Font f = new System.Drawing.Font(font[findex], 10, System.Drawing.FontStyle.Bold);
				Brush b = new System.Drawing.SolidBrush(c[cindex]);
				int ii=4;
				if((i+1)%2==0)
				{
					ii=2;
				}
				g.DrawString(checkCode.Substring(i,1), f, b, 3+(i*12), ii);
			}
//画一个边框
			g.DrawRectangle(new Pen(Color.Black,0),0,0,image.Width-1,image.Height-1);

//输出到浏览器
			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();
		}



eShaka

职务:版主
等级:6
金币:15.0
发贴:5019
#42004/11/29 8:53:29
正好需要^_^



蓝鲸

职务:版主
等级:5
金币:42.1
发贴:2614
#52004/11/29 9:50:18
等空些,我也去研究一下GDI+,应该很有用处。


非常大鱼

我佛山人

职务:版主
等级:4
金币:16.0
发贴:2269
#62004/11/29 11:39:40
我以前做的
cunite.com/vcode.aspx



缺缺

职务:管理员
等级:8
金币:41.0
发贴:9620
#72004/11/29 11:44:34
我佛山人在上个帖子中说
引用:
我以前做的
cunite.com/vcode.aspx


看一下代码



eShaka

职务:版主
等级:6
金币:15.0
发贴:5019
#82004/11/29 11:46:36
我佛山人在上个帖子中说
引用:
我以前做的
cunite.com/vcode.aspx


把源码发上来



eShaka

职务:版主
等级:6
金币:15.0
发贴:5019
#92004/11/29 15:51:28
命名空间有问题
除了using System.Drawing.Drawing2D;
还有什么啊??



eShaka

职务:版主
等级:6
金币:15.0
发贴:5019
#102004/11/29 15:52:57
System.Drawing.Imaging却却真好