最容易使用的验证码控件附代码.docx
- 文档编号:12788922
- 上传时间:2023-06-08
- 格式:DOCX
- 页数:56
- 大小:34.17KB
最容易使用的验证码控件附代码.docx
《最容易使用的验证码控件附代码.docx》由会员分享,可在线阅读,更多相关《最容易使用的验证码控件附代码.docx(56页珍藏版)》请在冰点文库上搜索。
最容易使用的验证码控件附代码
下面给大家介绍一个最容易使用的验证码控件CheckBot。
为吗说是最容易使用呢,因为我看到过的验证码控件都需要在IIS上做不少设置,或者还要拷贝一些特殊的文件到特定的目录,而且验证码图像与输入验证码的输入框外观设置起来也很麻烦(甚至你根本没法设置),而CheckBot则象标准控件一样,无需任何设置,而外观设置则遵循标准控件的统一标准。
让我来演示一下,首先你要把它放到工具箱里去,你要下载那个dll文件(
新建1个apsnet页,把CheckBot拖过去,你看到的应该是只是一个小图片,而没有收集用户输入的输入框。
验证码的图像和验证码输入框是分离的,这样设计的好处是很方便设置验证码这2部分的布局,你可以关联页面上任何一个可以收集用户输入文字的控件作为验证码输入框。
下面我说说如何让CheckBot关联一个收集用户输入文字的控件作为验证码输入框,现拖一个TextBox控件到页面上,然后查看CheckBot的属性窗口中的ControlForUserType属性,这是一个下拉框,点击一下,你就可以看到刚刚拖出来的TextBox控件就在列表里,实际上这个列表列出了页面上全部可以做为验证码输入框的控件。
这样第1步就设置完成了,你可以点下F5看到效果了。
是不是很容易呢,验证用户输入是否正确也很容易,下一步再拖一个Button到页面上,双击他跳转到它的处理程序,假设添加的CheckBot控件的ID为CheckBot1,添加这句代码Response.Write(CheckBot1.Validate());然后再按F5运行,当你在输入框中输入正确的验证码时,点击了Button会输出True,如果写错了,当然会输出False,也许你已经明白了,在代码中调用CheckBot1.Validate()就可以获得用户输入的验证码是否匹配。
通过上边的介绍,你是否也同意CheckBot很容易使用呢,实际上CheckBot不仅容易使用,而且很容易扩展,还方便部署,下边现给打家介绍下如何扩展验证码的绘制。
让我猜下你刚刚对CheckBot的感受,第1是它的确挺容易的,第2应该是它画出来的验证码图像太搓了吧,-_-!
!
真是不好意思,我还没找到个画验证码好法子,不过你完全可以方便的用你自己的方法来画验证码。
到刚才的页面去,双击下验证码图像,出现了protectedvoidCheckBot1_DrawText(objectsender,Gugu.CheckBotComponent.CheckBotDrawTextEventArgse){},在这个事件里你可以画验证码,事件参数e中包括了画验证码所必需的所有参数,e.Text就是要画的验证码文字,e.Graphics是绘图环境上下文,e.Graphics.DrawString()方法是很便利使用的,e.Rectangle则描绘了绘图表面的大小,还有些别的参数你可以从属性窗口查一下描述,相信你一定能画个比我强的多的验证码。
最后要提醒一下,CheckBot控件无法获知是否你在这个事件里什么也没做,如果真是那样,验证码图像会变成个全黑的图片,如果你想让其还原,则需要把刚才处理CheckBot1_DrawImageText()这个事件的代码全部删除。
既然画验证码的方法可以自己定制,那么验证码的中文字是否也可以自己定制呢?
那是当然的了,CheckBot.ImageText属性就是验证码中将绘制的文字,你可以用自己的方法每次赋一个随机的字符串值,千万别总是赋一个固定值给它,如果那样每次验证码的文字都一样啦。
CheckBot.ImageText属性的默认值为null,在其设置为null的情况下,CheckBot会自动生成随机的文字。
上边我说了CheckBot有一个DrawText事件,实际是CheckBot还有另外一个事件:
PreDrawText。
为吗CheckBot需要2个事件呢?
这和CheckBot的工作原理是分不开的。
我们知道1次Http请求,只能得到一种类型的Meta类型的回复,像输入框这种元素,是文本类型的,而验证码的图片,则是图像类型的,2者的类型不一样,所以一个完整的验证码不能够用1次Http请求完成,实际上是2次。
第1次请求获得输入框和第2次请求的参数,第2次请求获得验证码图像。
为了把第2次请求时页面不用处理的数据减到最小,在CheckBot的初始化过程中,CheckBot就完成了画图并把页面终止,所以写在其他位置的代码还没有执行,页面就结束了。
但是在第2次请求图像,CheckBot画图前会先后触发PreDrawText和DrawText2个事件,你可以在这个最后时刻做一些工作。
那么在PreDrawText中都可以做些啥工作呢?
修改CheckBot.Drawer属性,Drawer是实现了Gugu.CheckBotComponent.ICheckBotDrawer接口的一个类,实现这个接口的类都要实现DrawText()方法,而此方法可以实现一个画验证码的引擎。
这样,你可以把画验证码的引擎的代码与页面的代码分离,可以放到某一个模块里,或者来自另一个程序集。
请注意:
如果你想让刚刚在PreDrawText中赋值的CheckBot.Draw属性起作用,那一个不要截获DrawText事件,因为如果DrawText事件的监听不为空,CheckBot就会认为你要自己手动来画验证码,那么就会忽略CheckBot.Draw属性。
前边刚给大家介绍了CheckBot的一个主要组件:
CheckBot.Draw,实际CheckBot共有4个主要组件,另3个分别是CheckBot.Manager,CheckBot.Generator,CheckBot1.UrlCodes,这4部分都是可以分别订制,从而扩展你的验证码控件。
CheckBot.Manager是用来生成随机的验证码文字的,CheckBot1.UrlCodes则管理者着验证码图像中的参数的编码,从而实现第1次和第2次Http请求之间的信息交换,你可以随时用分别实现了Gugu.CheckBotComponent.ICheckBotGenerator接口和Gugu.CheckBotComponent.CheckBotUrlCodes接口的类更改验证码的行为方式。
CheckBot.Draw是画验证码的引擎。
最后CheckBot.Manager是最复杂的一个,它用来保存验证码的秘密,使客户端的计算机无法识别,同样对CheckBot.Manager属性的更改也有一点特殊的要求,因为第2次请求中画验证码图像是在init初始化中就完成了,所以要想更改CheckBot.Manager属性,必须在init事件之前完成,所以如果要更改CheckBot.Manager属性,务必把它写在Page.PreInint事件中。
CheckBot的确是有很大的灵活性,如果有1天,你在你的站点上很多个不同页面使用了CheckBot,但是某1天发现了有人写了1个更好的验证码画图引擎,并发布为了一个程序集dll文件,你想立即把站点上的所有CheckBot都使用新引擎,那么可以高兴得告诉你,你只需要改几个字母,并不需要修改全部这些页面就可以完成这个庞大的工作,CheckBot支持方便的部署。
你可以在站点的web.config文件中的
再大家聊聊验证码的细节,验证码的原理是客户发出第1个请求,服务器端生成一个随机字符串,和对应这个字符串的令牌,然后把令牌保存到回送的页面中,同时把令牌编码到第2次请求的Url参数里,这样第1次请求处理完毕,回送的页面包含了令牌和第2次请求的Url参数,而Url参数里也有同一个令牌;客户端获得第1次请求的回送后就开始第2次请求,服务器端处理第2次请求,并从Url参数里获得令牌,并通过此令牌查询对应的先期生成的字符串,然后画图,并把图像返回客户端;用户识别图像,并填写验证码,然后提交,服务器接受后,根据保存在页面中的令牌再次查询到先期生成的字符串,并与用户输入的进行比较,从而可以判断出用户输入是否正确。
可以看到在整个过程中客户端只获得一个令牌,而这个令牌并不包含对应字符串的任何信息,所以客户端的计算机无法通过令牌来识别验证码,唯一识别验证码的途径是识别第2次返回的图像,如果图像画的足够花里胡哨的话,客户端的计算机又识别不了,只能由人来识别,从而起到了预防机器人的作用。
话虽这么说,可是在服务器端保存1大堆的字符串还是很占资源的啊,所以CheckBot的默认实现并没有在服务器端保存字符串,而是把它加密了放到令牌里去了,这样的好处是解放了服务器,坏处自是不用说,危险重重啊。
不过把秘密放在客户端也不是一无是处,虽然客户端可以拿着这个令牌来冒充,但是我们还是有对付他的方法,方法就是过期。
CheckBot.ExpectantPeriod就是用来设施过期时间的,初始为5分钟。
对CheckBot的默认实现来说就是保存到客户端的令牌只有5分钟的有效期,如果有人拿着一个冒充的令牌大发淫威的话,他只能疯狂5分钟,5分钟后他得再去自己识别另一个图片,所以客户端保存秘密如果受到攻击,最多是个半自动的,而不会是全自动的。
如果你决定让半自动的的攻击也不可能,就可以把秘密保存到服务器端,在Gugu.CheckBotComponent名称空间下有另外一个类:
CheckBotManageerSaveAtServer,它就是把秘密保存到了服务器端,你可以在Page.PreInit事件中把CheckBot.Manager属性设置为CheckBotManageerSaveAtServer,字符串的秘密的保存就要辛苦服务器了。
前边提到了CheckBot.ExpectantPeriod属性,你可能会奇怪怎么不直接叫Period,而叫ExpectantPeriod,因为对秘密保存在服务器端的验证码可以保证几年也不过期,而对把秘密保存在客户端验证码则必须很快过期,所以具体的过期策略最终是由CheckBot.Manager来管理的,所以就成了期望的过期时间,CheckBot中以Expectant大头的属性还有几个,原因和这差不多。
既然有了过期时间,那么在验证用户输入验证码失败就有2种情况了,可能是输入错了,也可能是验证码过期造成的,那对于页面作者来说能区分这2种情况吗?
当然能啊,CheckBot.ValidatedTimeOut是一个bool属性,如果他返回为false,就说明验证失败失败是由于验证码过期造成的。
某人说说起来是1回事,做起来是另会事,真是如此啊,再让我说下去是我设想的1大堆不足或错误还有构想,好像怎么也改不完,欢迎你使用这个验证码控件,有任何意见或建议请致邮件gugu2000cec(AT),编译了的dll和cs文件应该可以在
//***********************代码开始**************************************//
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
//控件名称:
Gugu.CheckBot--验证码(.Net版本:
2.0)
//版本:
1.0.0.0
//作者:
Gugu
//邮箱:
gugu2000cec(AT)
//时间:
2006-9-5
namespaceGugu
{
#regionCheckBot
//存在的首要问题:
返回验证码图像的调用并没有像设想的那样在init事件后终止,猜测是因为权限不足造成的,一个控件怎么有权力终止一个页面的呈现呢。
//测试中曾出现了出个黑方框未知异常。
///
///验证码控件
///
[System.ComponentModel.DefaultProperty("ControlForUserType")]
[System.ComponentModel.DefaultEvent("DrawImageText")]
[System.ComponentModel.Designer(typeof(Gugu.CheckBotComponent.CheckBotDesigner))]
[System.ComponentModel.Description("验证码控件")]
publicsealedclassCheckBot:
System.Web.UI.WebControls.Image
{
#regionConst
privateconststringGUID="fdcd854648e1478f808046474654c7c5";
///
///验证码图像允许的最大宽度。
///
publicconstintImageMaxWidth=800;
///
///验证码图像允许的最小宽度。
///
publicconstintImageMinWidth=50;
///
///验证码图像允许的最大高度。
///
publicconstintImageMaxHeight=600;
///
///验证码图像允许的最小高度。
///
publicconstintImageMinHeight=25;
#endregion
#region创建模式部分
privatestaticGugu.CheckBotComponent.ICheckBotFactoryFactory;
staticCheckBot()
{
//异常处理:
//已预见的异常有4处:
//1.*AssemblyName输入错误,系统会找不到文件,触发System.IO.FileNotFoundException异常。
//2.*AssemblyVersion版本输入错误,系统无法引导正确的程序集,触发System.IO.FileLoadException异常。
//3.*Factory设置的类没有实现I*Factory接口时会触发System.InvalidCastException异常。
//前三种异常系统的默认说明清楚明白,我就不用再捕获了。
//4.*Factory类名称输入错误,系统会把*Factory设置为Null,或者没有输入*Factory的情况下,CheckBot控件自动查找的过程中没有找到相应的实现了接口的类,
//也会把*Factory设置为Null,在staticCheckBot()中不会触发异常,但会在别的代码中触发System.NullReferenceException异常,这个异常会使用户很困惑,
//所以应该捕获第4种异常并给出相应说明。
//强名处理?
//国际化的支持?
conststringan="CheckBotFactoryAssemblyName";
conststringav="CheckBotFactoryAssemblyVersion";
conststringcn="CheckBotFactoryClassName";
if(System.Web.Configuration.WebConfigurationManager.AppSettings[an]!
=null)
{
System.Reflection.AssemblyNameassemblyName=newSystem.Reflection.AssemblyName(System.Web.Configuration.WebConfigurationManager.AppSettings[an]);
if(System.Web.Configuration.WebConfigurationManager.AppSettings[av]!
=null)
assemblyName.Version=newSystem.Version(System.Web.Configuration.WebConfigurationManager.AppSettings[av]);
System.Reflection.Assemblyassembly=System.Reflection.Assembly.Load(assemblyName);
if(System.Web.Configuration.WebConfigurationManager.AppSettings[cn]!
=null)
{
CheckBot.Factory=(Gugu.CheckBotComponent.ICheckBotFactory)
assembly.CreateInstance(System.Web.Configuration.WebConfigurationManager.AppSettings[cn]);
if(CheckBot.Factory==null)
thrownewGugu.CheckBotComponent.CheckBotException("WebConfig中CheckBotFactory设置的"
+System.Web.Configuration.WebConfigurationManager.AppSettings[cn]+"实例化为ICheckBotFactory失败。
");
}
else//自动查找
{
System.Type[]types=assembly.GetTypes();
foreach(System.Typetypeintypes)
{
System.Type[]interfaces=type.GetInterfaces();
foreach(System.Typeinterface_ininterfaces)
{
if(interface_==typeof(Gugu.CheckBotComponent.ICheckBotFactory))
{
CheckBot.Factory=(Gugu.CheckBotComponent.ICheckBotFactory)assembly.CreateInstance(type.FullName);
break;
}
}
}
if(CheckBot.Factory==null)
{
stringstr="\""+System.Web.Configuration.WebConfigurationManager.AppSettings[an];
if(System.Web.Configuration.WebConfigurationManager.AppSettings[av]!
=null)
str+="Version="+System.Web.Configuration.WebConfigurationManager.AppSettings[av];
str+="\"中没有实现ICheckBotFactory接口的类。
";
thrownewGugu.CheckBotComponent.CheckBotException(str);
}
}
}
else
CheckBot.Factory=newGugu.CheckBotComponent.CheckBotFactory();
}
///
///初始化验证码控件
///
publicCheckBot()
{
//Gugu.CheckBotComponent.CheckBotManagertemp=newGugu.CheckBotComponent.CheckBotManager();
//manager_=temp;
//image_url_codes=temp;
}
privateGugu.CheckBotComponent.ICheckBotGeneratorgenerator_=CheckBot.Factory.GetCheckBotGenerator();
///
///管理生成随机文字
///
[System.ComponentModel.Browsable(false)]
[System.ComponentModel.Description("管理生成随机文字")]
publicGugu.CheckBotComponent.ICheckBotGeneratorGenerator
{
get
{
if(this.generator_==null)
this.generator_=newGugu.CheckBotComponent.CheckBotGenerator();
returnthis.generator_;
}
set{this.generator_=value;}
}
privateGugu.CheckBotComponent.ICheckBotDrawerdrawer_=CheckBot.Factory.GetCheckBotDrawer();
///
///管理绘制验证码文字
///
[System.ComponentModel.Browsable(false)]
[System.ComponentModel.Description("管理绘制验证码文字")]
publicGugu.CheckBotComponent.ICheckBotDrawerDraw
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 容易 使用 验证 控件 代码
![提示](https://static.bingdoc.com/images/bang_tan.gif)