为了明天

时光匆匆流逝, 笑看风起云落 - 流浪的狗2006

Asp.net(C#)实现验证码功能

新建一个专门用来创建验证码图片的页面ValidateCode.aspx
它的后台cs文件代码如下:
PageLoad

private void Page_Load(object sender, System.EventArgs e)
        
{
            
string checkCode = CreateRandomCode(4);
            Session[
"CheckCode"= checkCode;
            CreateImage(checkCode);
        }

其中CreateRandomCode是自定义的函数,参数代表验证码位数

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" ;
            
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(35);
                
if(temp == t)
                
{
                    
return CreateRandomCode(codeCount);
                }

                temp 
= t;
                randomCode 
+= allCharArray[t];
            }

            
return randomCode;
        }

CreateImage也是一个自定义的函数,用于生成图

private void CreateImage(string checkCode)
        
{
            
int iwidth = (int)(checkCode.Length * 11.5);
            System.Drawing.Bitmap image 
= new System.Drawing.Bitmap(iwidth, 20);
            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.Blue);
            g.DrawString(checkCode, f, b, 
33);

            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.Width,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();
        }

//g.FillRectangle(new System.Drawing.SolidBrush(Color.Blue),0,0,image.Width, image.Height);
g.Clear(Color.Blue);
这两种方法都可以改变生成图片的背景颜色
下面那个for循环用来生成一些随机的水平线

在需要用到验证码的页面添加一个<asp:Image>控件即可,但是要把ImageUrl指向生成验证码的页面

<asp:Image Runat="server" ID="ImageCheck" ImageUrl="ValidateCode.aspx"></asp:Image>

posted on 2004-10-20 17:03 流浪的狗 阅读(21054) 评论(60)  编辑 收藏 网摘 所属分类: Dotnet C#

评论

#1楼  2004-10-20 19:51 Tmouse      

正需要,谢谢。   回复  引用  查看    

#2楼  2004-10-21 08:44 灵感之源      

1、字符串的每个字符的字体都随机?
2、字符串的每个字符的位置都随机?如上下,倾斜等等
3、既然有垂直线,那干脆把水平线也加上,而且这些先的位置和数量应该是随机的;
4、干脆把弄写随机点吧:)   回复  引用  查看    

#3楼 [楼主] 2004-10-21 09:12 边城浪子      

这个只是初步实现了验证码的功能,其它的我都还没有考虑呢。
1,字体随机。这个应该可以做到,不难。
2,位置随机。上下应该可以做到,只是倾斜不好办,难道用斜体代替?
3,水平线。加上不难,只是这个加多了就会阻碍用户识别了吧。
4,不明白什么意思

谢谢灵感之源哦   回复  引用  查看    

#4楼  2004-10-21 17:06 Goodspeed      

能让背景透明的吗?   回复  引用  查看    

#5楼  2004-10-21 23:02 myxname      

你这样做来点IE后退骓证码不变的吧. 我原来这样做的.后来改为:
<script>document.write("<img src='ValidateImg.aspx?strimg=",Math.random(),"' >");</script> 这样点IE的后退都重生成.   回复  引用  查看    

#6楼  2004-10-21 23:12 myxname      

灵感之源的随机点就是背景改为那小数点的. 那样不要垂直线,水平线了, 有时在别人网上可以看到这样的.
有个方法是直接加一张小点点的背景图,然后在上面写字. 有点像水印了哦.:P   回复  引用  查看    

#7楼 [楼主] 2004-10-22 11:26 边城浪子      

to myxname
试过了,还是不会变
这个应该和在哪个页面验证有关
如果就在当前页进行验证的话还是不会改变   回复  引用  查看    

#8楼  2004-11-17 02:08 蜗牛 [未注册用户]

那么在页面如何知道这个验证码的值

if ( lblValidate.Text = ViewState["CheckCode"] )
{
lblDisplay.Text = "验证通过";
}
else
{
lblDisplay.Text = "所填写的验证码与所给的不符";
}
为什么不行的?   回复  引用    

#9楼 [楼主] 2004-11-17 13:12 边城浪子      

to 蜗牛:
Session["CheckCode"] = checkCode;
不是放在ViewState里的,是放在Session里的   回复  引用  查看    

#10楼  2004-11-17 17:50 蜗牛 [未注册用户]

if ( lblValidate.Text == Session["CheckCode"].ToString())
{
lblDisplay.Text = "验证通过";
}
else
{
lblDisplay.Text = "所填写的验证码与所给的不符";
}
为什么老提示“所填写的验证码与所给的不符”   回复  引用    

#11楼 [楼主] 2004-11-17 19:25 边城浪子      

具体的我也不太清楚
你监视一下程序
看看生成的checkcode和页面上显示的是否一致   回复  引用  查看    

#12楼  2004-11-17 22:01 蜗牛 [未注册用户]

我就是用你的程序,然后在login.aspx调用。
我要显示Session["CheckCode"].ToString(); 的值,但出现错误。
错误:未将对象引用设置到对象的实例。   回复  引用    

#13楼  2004-11-18 10:37 qqq [未注册用户]


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" ;
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(35);
if(temp == t)
{
return CreateRandomCode(codeCount);
}
temp = t;
randomCode += allCharArray[t];
}
return randomCode;
}
  回复  引用    

#14楼  2004-11-18 10:38 ddddddddddddd [未注册用户]

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace WebApplication2
{
/// <summary>
/// ValidateCode 的摘要说明。
/// </summary>
public class ValidateCode : System.Web.UI.Page
{
private void Page_Load(object sender, System.EventArgs e)
{
// 在此处放置用户代码以初始化页面
string checkCode = CreateRandomCode(4);
Session["CheckCode"]=checkCode;
CreateImage(checkCode);

}

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" ;
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(35);
if(temp == t)
{
return CreateRandomCode(codeCount);
}
temp = t;
randomCode += allCharArray[t];
}
return randomCode;
}

private void CreateImage(string checkCode)
{
int iwidth = (int)(checkCode.Length * 11.5);
System.Drawing.Bitmap image = new System.Drawing.Bitmap(iwidth, 20);
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.Blue);
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.Width,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();
}

#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
}
}
  回复  引用    

#15楼  2004-11-20 13:48 我阿犬 [未注册用户]

TO:蜗牛
if (Page.IsPostBack )
{
if(TxtRand.Value.ToString()== Session["CheckCode"].ToString())
{
Response.Write("111");
Response.End();
}
}
你窗体刚加载Session当然没有了 这个对象你既没有定义null 又没声明
即使if(Session["CheckCode"]==null)也会出错 得等窗体提交的时候
因为窗体初始的时候动态图片正在生成中 Session也在创建中。
这个写的比http://www.21tx.com/dotnet/wz/37WKOBMXZZPN1NJCHS.shtml
这里的好,可是作者有个函数写的不好,影响性能如下:
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" ;
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(35);
if(temp == t)
{
return CreateRandomCode(codeCount); //这里如果随机数字经常重复就是死循环了,当然不能经常重复,但是整个函数又要重新开始,影响性能是不是????????
}
temp = t;
randomCode += allCharArray[t];
}
return randomCode;
}
return CreateRandomCode(codeCount); //这里如果随机数字经常重复就是死循环了,当然不能经常重复,但是整个函数又要重新开始,影响性能是不是????????
  回复  引用    

#16楼  2004-12-01 15:15 初学者 [未注册用户]

谢谢!
不过随机横线有时候会妨碍识别。
不知能否提供贵站所使用的验证图片生成代码啊?:)   回复  引用    

#17楼 [楼主] 2004-12-01 19:22 边城浪子      

贵站?
你是说博客园么?
这里的老大是dudu
你去问问他吧
http://www.cnblogs.com/dudu   回复  引用  查看    

#18楼  2004-12-09 20:20 ^o^ 毛毛 ^o^ [未注册用户]

请问

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

这一句是做什么用的啊?   回复  引用    

#19楼  2004-12-11 15:04 111 [未注册用户]

【摘要】
全球网络的普及,使得网站建设的地位变得不可动摇!互联网随之而然地成为了人们生活中的必须!个人网页的制作已逐渐广泛,能够拥有体现自己个性的网页,就必须体现自己的优势,使网页动态化。
用ASP这种动态服务器网页配合后台链接的数据库SQL,ACCESS等对自己网站论坛的内容增加审核功能即所有网友发到论坛的文章,并不立即被显示出来,必须经过站长或者版主审阅之后,认为有价值,有必要推荐给其它网友的,就发表出来。否则就删掉了,免得浪费空间,,这样的论坛能够提供给为明确有益的内容放到网站上,能够吸引更多的网友来访问。

关键词:ASP动态服务器,SQL,ACCESS,数据库,后台链接,论坛

  回复  引用    

#20楼  2004-12-22 10:03 Chap [未注册用户]

要是能实现这个页面所用的验证图片就好了!   回复  引用    

#21楼  2004-12-23 17:14 Deboy_W [未注册用户]

Random r = new Random();
for(int i = 0;i<codeCount;i++)
{
randomCode += allCharArray[r.Next(0,35)];
}
这样有什么不好/   回复  引用    

#22楼  2004-12-25 13:50 234 [未注册用户]

博客的随机码是怎么弄得
有没有好看一点
  回复  引用    

#23楼  2004-12-25 14:18 阿斗分 [未注册用户]

怎样把背景弄成透明的   回复  引用    

#24楼  2005-01-12 10:31 Richard [未注册用户]

我这样调用,也提示未将对象引用设置到对象的实例
行 62: if (strValidate.Text.Trim() == Session["CheckCode"].ToString().Trim())


private void btnLogin_Click(object sender, System.EventArgs e)
{
string tmpErrMsg = "";
if (strValidate.Text.Trim() == Session["CheckCode"].ToString().Trim())
{
tmpErrMsg = tmpErrMsg.ToString().Trim() + "验证码匹配失败!<br>";
}
ErrMsg.Text = tmpErrMsg;
}   回复  引用    

#25楼 [楼主] 2005-01-12 10:39 边城浪子      

确保你的Session["CheckCode"]存在
不存在的就不能ToString()了

所以最前面应该加上判断   回复  引用  查看    

#26楼  2005-02-19 13:58 SW515 [未注册用户]

本人也写了一个这样的,见笑了:

http://blog.csdn.net/sw515/archive/2005/02/03/279364.aspx   回复  引用    

#27楼  2005-02-19 14:00 SW515 [未注册用户]

本人也写了一个这样的,见笑了:
http://blog.csdn.net/sw515/archive/2005/02/03/279364.aspx


效果图:
http://blog.csdn.net/images/blog_csdn_net/sw515/17120/o_CheckCode.gif
  回复  引用    

#28楼  2005-02-19 14:07 SW515 [未注册用户]

本人也写了一个这样的,见笑了:
http://blog.csdn.net/sw515/archive/2005/02/03/279364.aspx


效果图:
http://blog.csdn.net/images/blog_csdn_net/sw515/17120/o_CheckCode.gif
  回复  引用    

#29楼  2005-02-19 14:49 SW515 [未注册用户]

本人也写了一个这样的,见笑了:
http://blog.csdn.net/sw515/archive/2005/02/03/279364.aspx


效果图:
http://blog.csdn.net/images/blog_csdn_net/sw515/17120/o_CheckCode.gif
  回复  引用    

#30楼  2005-02-23 09:03 nanfansky [未注册用户]

性能问题,建议改改CreateRandomCode函数
发现前面有人提过了,修改如下

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,V,W,X,Y,Z";
string[] allCharArray = allChar.Split(Convert.ToChar(","));
string RandomCode = "";
int temp = -1;

Random rand = new Random();
for (int i=0;i<CodeCount;i++)
{
if (temp != -1)
{
rand = new Random(temp*i*((int) DateTime.Now.Ticks));
}

int t = rand.Next(35);

while (temp == t)
{
t = rand.Next(35);
}

temp = t;
RandomCode += allCharArray[t];
}

看是否合适?   回复  引用    

#31楼  2005-02-23 09:46 nanfansky [未注册用户]

性能与取Z字母
对CreateRandomCode函数的修改:
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,V,W,X,Y,Z";
string[] allCharArray = allChar.Split(Convert.ToChar(","));
string RandomCode = "";
int temp = -1;

Random rand = new Random();
for (int i=0;i<CodeCount;i++)
{
if (temp != -1)
{
rand = new Random(temp*i*((int) DateTime.Now.Ticks));
}

int t = rand.Next(36);

while (temp == t)
{
t = rand.Next(36);
}

if (t==35)
{
Console.WriteLine(t.ToString() + "|" + i.ToString());
}
temp = t;
RandomCode += allCharArray[t];
}

return RandomCode;
}   回复  引用    

#32楼  2005-03-11 13:47 baoaya [未注册用户]

//history back 不重复
Response.Cache.SetNoStore();//这一句
Response.ClearContent();
Response.ContentType = "image/Jpeg";
Response.BinaryWrite(ms.ToArray());

//增加一个验证的函数
public static bool CheckCode(string strCode)
{
strCode=strCode.ToUpper();
string strSessionCode=System.Web.HttpContext.Current.Session["CheckCode"]+"";
strSessionCode=strSessionCode.ToUpper();
System.Web.HttpContext.Current.Session["CheckCode"]=null;//注意要清空,防止一个session时间内攻击
return (strSessionCode==strCode);
}   回复  引用    

#33楼  2005-03-18 18:29 hubro [未注册用户]

http://www.hubro.net/?id=40   回复  引用    

#34楼  2005-07-06 10:39 高天蒲 [未注册用户]

今天看到大哥的文章,
受益无穷,谢谢啦。
等忙过这阵子了,
我把它封装成web控件,
届时请你指点!!!
  回复  引用    

#35楼  2005-07-31 20:37 newfay [未注册用户]

CSDN上的文章,比这篇经典
http://dev.csdn.net/article/73/73816.shtm   回复  引用    

#36楼  2005-08-04 21:17 jeky [未注册用户]

这段时间,我主页上的留言簿垃圾真是多多。
呵呵,刚才我把验证码加上了:
http://www.jeky.cn/pages/write.aspx
  回复  引用    

#37楼  2005-08-13 17:04 uio [未注册用户]

如果进入到登陆页,不提交登陆,我的好象就出错了.

未将对象引用设置到对象的实例。   回复  引用    

#38楼  2005-08-15 20:39 stdcall [未注册用户]

有内存漏洞啊:
“System.IO.MemoryStream ms = new System.IO.MemoryStream();”
既然用了非托管资源就要在后面释放:
ms.Close();
ms.Dispose();
  回复  引用    

#39楼  2005-08-23 10:02 1 [未注册用户]

1   回复  引用    

#40楼  2005-09-25 21:45 肖 [未注册用户]

abc
  回复  引用    

#41楼  2006-05-13 09:46 最新韩剧 [未注册用户]

正需要   回复  引用    

#42楼  2006-05-26 23:17 杨帆 [未注册用户]

计划 可,旧 民间美女 没美女年   回复  引用    

#43楼  2006-07-04 21:28 yji [未注册用户]

uk+
  回复  引用    

#44楼  2006-09-17 19:16 psoft129      

在检查验证码的页面里面访问的是前一次生成的验证码!?

作者能给个解释吗?
谢谢   回复  引用  查看    

#45楼  2006-10-14 10:24 手机语音自动应答软件 自动应答 播放语音 挂掉电话 (应答语音自己随心录制) 自动语音应答 [未注册用户]



正在找。 多谢!!   回复  引用    

#46楼  2006-10-26 17:28 byhum [未注册用户]

为什么我使用了作者的程序之后页面上所有的控件都不见了?只有验证码图片存在?   回复  引用    

#47楼  2006-11-11 15:34 sf [未注册用户]

sdsdsf   回复  引用    

#48楼  2007-01-13 15:20 yy[匿名] [未注册用户]

谢谢楼上所有的网络朋友们!   回复  引用    

#49楼  2007-01-15 20:10 madwww [未注册用户]

真的很不错   回复  引用    

#50楼  2007-04-15 15:31 jiang [未注册用户]

thank you very much   回复  引用    

#51楼  2007-05-17 15:20 hih [未注册用户]

[url=http://www.zhangxiu.com/send/send.html?move=false&name=为爱而生&f=11405]为爱而生[/url]
[url=http://www.zhangxiu.com/send/send.html?move=false&name=逆光&f=11405]逆光[/url]
[url=http://www.zhangxiu.com/send/send.html?move=false&name=发现爱&f=11405]发现爱[/url]
[url=http://www.zhangxiu.com/send/send.html?move=false&name=爱情转移&f=11405]爱情转移[/url]
[url=http://www.zhangxiu.com/send/send.html?move=false&name=菊花台&f=11405]菊花台[/url]
[url=http://www.zhangxiu.com/send/send.html?move=false&name=离歌&f=11405]离歌[/url]
[url=http://www.zhangxiu.com/send/send.html?move=false&name=死了都要爱&f=11405]死了都要爱[/url]
[url=http://www.zhangxiu.com/send/send.html?move=false&name=今天你要嫁给我&f=11405]今天你要嫁给我[/url]
[url=http://www.zhangxiu.com/send/send.html?move=false&name=隐形的翅膀&f=11405]隐形的翅膀[/url]
[url=http://www.zhangxiu.com/send/send.html?move=false&name=月亮之上&f=11405]月亮之上[/url]
[url=http://www.zhangxiu.com/send/send.html?move=false&name=秋天不回来&f=11405]秋天不回来[/url]
  回复  引用    

#52楼  2007-06-29 11:21 网友 [未注册用户]

怎么实现点击图片刷新编码呢?   回复  引用    

#53楼  2007-08-05 16:09 星光 [未注册用户]

很好,谢谢!   回复  引用    

#54楼  2007-09-14 14:44 CNNBT [未注册用户]

private void Page_Load(object sender, System.EventArgs e)
{
string checkCode = CreateRandomCode(4);
Session["CheckCode"] = checkCode;
CreateImage(checkCode);
Response.Cache.SetCacheabilit(HttpCacheability.NoCache);
}

IE后退,验证码也改变   回复</