是不是看到题目一脸懵逼^_^,换句人话其实就是验证码,验证码是网站做人机区分的一种常用手段。想必大家对12306的BT验证码还历历在目吧,尽管遭到无数的吐槽和调侃,但是不可否认验证码作为一种辅助安全手段在Web安全中起着重要的作用,可以一定程度上防止恶意破解密码、刷票、论坛灌水等非法操作。这里我们就来探究一下目前的一些验证码解决方案及其安全性。
全自动区分计算机和人类的图灵测试(英语:Completely Automated Public Turing test to tell Computers and Humans Apart,简称CAPTCHA),俗称验证码。
Google Kaptcha Kaptcha 是一个验证码生成引擎,axet使得基于maven的工程可以很方便的集成自己的项目中,只需要在pom中添加以下依赖即可。
1 2 3 4 5 6 7 <dependencies > <dependency > <groupId > com.github.axet</groupId > <artifactId > kaptcha</artifactId > <version > 0.0.9</version > </dependency > </dependencies >
示例的controller代码如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 @Controller public class CaptchaController { @Resource private Producer producer; @Autowired private RedisService redisService; @RequestMapping (value="/captcha/{verification_key}" ) public ModelAndView getPostCodeKaptchaImage (HttpServletRequest request, @PathVariable("verification_key" ) String verification_key,HttpServletResponse response) throws Exception { try { response.setDateHeader("Expires" , 0 ); response.setHeader("Cache-Control" , "no-store, no-cache, must-revalidate" ); response.addHeader("Cache-Control" , "post-check=0, pre-check=0" ); response.setHeader("Pragma" , "no-cache" ); response.setContentType("image/jpeg" ); if (StringUtils.isNotBlank(verification_key)) { String capText = producer.createText(); redisService.createVerification(verification_key, capText); BufferedImage bi = producer.createImage(capText); ServletOutputStream out = response.getOutputStream(); ImageIO.write(bi, "jpg" , out); try { out.flush(); } finally { out.close(); } } } catch (Exception e) { } return null ; } }
Kaptcha提供比较丰富的配置参数,可以在Producer的实现类DefaultKaptcha自动装载的时候进行相关配置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 <bean id ="producer" class ="com.google.code.kaptcha.impl.DefaultKaptcha" > <property name ="config" > <bean class ="com.google.code.kaptcha.util.Config" > <constructor-arg > <props > <prop key ="kaptcha.image.width" > 70</prop > <prop key ="kaptcha.image.height" > 30</prop > <prop key ="kaptcha.textproducer.char.string" > 0123456789</prop > <prop key ="kaptcha.textproducer.char.length" > 4</prop > <prop key ="kaptcha.border" > no</prop > <prop key ="kaptcha.border.color" > 105,179,90</prop > <prop key ="kaptcha.border.thickness" > 1</prop > <prop key ="kaptcha.textproducer.font.color" > 0,0,0</prop > <prop key ="kaptcha.textproducer.font.size" > 20</prop > <prop key ="kaptcha.textproducer.font.names" > Courier</prop > <prop key ="kaptcha.noise.impl" > com.google.code.kaptcha.impl.NoNoise</prop > <prop key ="kaptcha.noise.color" > 100,100,100</prop > <prop key ="kaptcha.obscurificator.impl" > com.google.code.kaptcha.impl.ShadowGimpy</prop > <prop key ="kaptcha.textproducer.char.space" > 3</prop > </props > </constructor-arg > </bean > </property > </bean >
最后在你需要展示验证码的html中加上<img class="captcha" src="/captcha/uuid" alt="验证码">
便可以看到如下所示的预览效果。
captcha就是一款典型的传统验证码解决方案,目前此类验证码的安全性已经很低甚至于形同虚设,可以轻松的被光学字符识别(OCR, Optical Character Recognition)之类的电脑程序自动辨识,因此并不适合应用于安全性要求较高的场合。
Google reCAPTCHA reCAPTCHA是Google推出的一种“简化”的图灵测试,可以通过一种更简单的方法来判断机器人:点击一个复选框。也就是说你只需要像下图一样勾选“我不是机器人(I’m not a robt)”,谷歌便能够识别出是人或者机器的一次操作。这是因为reCaptcha功能会在“不经意间”收集大量信息,包括IP地址和cookies,然后通过收集这些数据看对方是否和过去在互联网上的行为一致,来判定这个用户究竟是不是机器人。尽管reCAPTCHA相对于传统手动输入的验证码相比对用户更加友好,但还是有人担心谷歌过度收集用户信息,并且网上也出现了一些破解算法。
geetest 国产验证码解决方案极验(点击体验) ,利用行为判别算法,用户只需要轻轻拖动滑块即可完成验证。个人觉得在体验和安全性上较传统的验证码形式都更好的表现,还带有一点点趣味性,唯一美中不足的是免费版的有1000次/小时的累积验证量限制,安全性也较收费版更低。
Reference [1]. kaptcha [2]. Googlere CAPTCHA [3]. 极验