初谈验证码与验证码设计
伴随着信息的泛滥,伴随着程序的“智能化”,以至于我们都不能识别网络的另一方是一个人还是一只猴子。为了识别对方是不是一只猴子,人们使用了一种 全自动区分计算机和人类的测试的技术,来防止这种现象,英文全称Completely Automated Public Test to tell Computers and Humans Apart。
验证码一般应用在需要控制有效信息输入的情况下,最常见的就是用户注册、登录、投票等。Google的验证码也应用在用户控制上,如Gmail中,当输入的错误用户名后,随便怎么都不会有验证码出现,但是当用户名正确的情况下,且输入密码错误超过两次,则会出现验证码,这是一个比较完善和安全的验证码。
验证码的设计
这里只涉及到一个较简单的验证码设计思路。
(1) 验证码的获取。
验证码一般都通过一个类似接口地址动态获取,例如http://www.impng.com/getCaptcha.php?auth=aXBmfFhEUFxFfDEyNTcxNzcwNTk。
(2) 验证码的有效性验证。
验证码的有效性验证可以通过session验证,明文记录在session中。验证通过后一定要注销该session,这是很常见的安全隐患点。
还有以参数形式带在URL中,不像session受会话限制,可以自由的在多台服务器下做验证,这也是在服务器集群下不能做到session同步的一种变相解决方法,但是这样的方法,需要把验证码明文带到页面中,因此需要采取加密后的串,并且是可逆的加密。
(3) 验证码的显示。
验证码一般带有背景噪点或者干扰线,但这不应该影响到对正常字符的识别。现在的应用很多都不使用背景噪点,干扰线使用的较多。
验证码的体验
在使用验证码的过程中,需要考虑到用户的体验度。
(1) 验证码字体处理。
验证码字符需要基于一个字体或者字体矩阵来生成。在字体的选择上,需要明显区分容易混淆的字符,如0和O,1和l、I等。
对于选取的字体中含有其他不使用到的字符,应该删除,以减小字体文件大小,如在只出现数字的验证码字符中,应该删除字体中的字母、符号。对于不用的中文字体来说,删掉它们会使上M的体积减小很多。
(2) 验证码的显示。
需要明确的是,对于真正的用户来说,验证码是一种没有必要的措施,不需要验证码的时候千万不要使用。就像Gmail的验证码,只有密码输入错误次数达到两次以上才会出现验证码,防止恶意暴力破解。
对于文字留言或者评论中使用验证码,可以参照Qzone的处理方式(虽然在某些方面来说,Qzone这里做的不好),在页面打开的时候不显示验证码,只有当用户点击输入框,即代表用户想发表评论的时候,才会显示验证码。采取这样的方式也可以减少请求验证码图片的资源耗费,毕竟不是每个看文章的人都想评论,但需要考虑如何使验证码的显示不唐突。
当显示的验证码字符不容易识别时,应该引导用户主动进行操作刷新验证码,而不跳转页面。为了防止浏览器缓存,需要在获取验证码图片的URL后带上一个随机数。
(3) 验证码的半智能化。
若可以确定只是数字型的验证码,那么就不应该让用户输入数字外的字符。
若确定是5位的验证码,那么当输入不等于5位的时候,就不应该提交服务器进行判断。这是最简单的客户端判断方法,避免不必要的服务器连接验证的消耗。
避免用户输入全角的字符,或者对于英文验证字符而在中文输入法状态操作。这时候,“ime-mode: disabled;”可以派上用场。
当用户输够验证码位数后,可以“自作聪明”的帮用户将焦点移到下一个元素上。
(4) 验证码的可用性。
当验证码图片无法显示时,或者用户无法识别验证码时,需要有其他的替代方案。Google或者Space就提供了声音识别方案。但是,将验证码明文显示在图片的alt属性中绝对不是一个好办法。对于用户注册时遇到的无法识别验证码的问题,最简单的解决办法莫过于提醒用户:打电话给客服通过。
验证码的突破
攻防兼顾,设计一个完善而安全的验证码,就需要知道怎么破解验证码。对于那些机制不完善的验证码,如验证码明文直接写在cookie中,不加密或简单加密带在获取验证码图片的url参数中等,轻而易举的就可以突破。
验证码中的字符无非是对现有字符的缩放、旋转、变色、扭曲等,针对这些方法,一一破解之。一般可以采取下面的步骤破解:
- 字模制作。验证码无非是采用若干种字体或者一些阵列字符的字体,采集一批验证码图片,分析下规律,做成字模。设计验证码的时候,若偷懒直接采用某些字体会很危险。
- 图片切割和去噪。将验证码图片切割为一个个的字符,切去空白部分,方便套字模。很多验证码都带有背景噪点或者干扰线,需要对图像进行运算处理,尽可能去除。图片切割的程度影响到字模的匹配。对于类似Google这种有粘连的字符,识别是很难的。
- 匹配。
更有人提出一种变相的突破方法,把验证码嵌入到美女图片站,每输入一个验证码才能看下一幅图片,为了某些目的,还是有很多人会不嫌麻烦的输入。
对于某些多样性的验证码,突破就很困难,但是一般这样的验证码都会损失一定的用户体验,用户自己都不好识别或者不好输入。早期的腾讯QQ注册和现有号码安全部分采用的中文验证码,和现在网易采用的两位中文验证码,涉及到中文就复杂些,更有做成SWF格式或GIF格式的,字符是浮动的,需要取帧来做判断。
如果你有兴趣,可以看看: