家好!我是黑客之家小编,黑客之家头条号
分享黑客技术,GO、Python、Kotlin、Android、Java编程知识,科技资讯等
喜欢的朋友可以关注我的头条号!
图形验证码是我们经常会用到的,例如在app或者网站注册的时候,登录的时候等等。图形验证码属于验证码的一种。
图形验证码
验证码(CAPTCHA)是 “Completely Automated Public Turing test to tell Computers and Humans Apart”(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机还是人的公共全自动程序。
采用图形验证码是为了数据的安全,防止某些破解软件,进行无限尝试破解,图形的话,软件无法识别,或识别的慢,这样更加安全。
理论上图形验证码是比较安全的,但是随着技术的发展,特别是机器学习和人工智能技术的发展,图形验证码也变得不安全了,今天我们将要生成的数字字母组合的验证码,其实已经不够安全了,生成效果如下:
这种验证码还是容易被机器识别的,后续的文章中会介绍如何采用程序识别这类图形验证码。
接着说图形验证码的生成,今天我们采用的是kaptcha。kaptcha是一个可配置验证码生成工具包,我们按照kaptcha的配置表配置就可以了。
在使用kaptcha之前,要导入kaptcha的包,依赖如下:
<dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency>
在Spring Boot项目中新建一个KaptchaConfig.java文件,具体代码如下:
package com.example.demo.config; /** * Created by hacker on 2019-07-16. */ import com.google.code.kaptcha.impl.DefaultKaptcha; import com.google.code.kaptcha.util.Config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.Properties; /** * @author hacker */ @Configuration public class KaptchaConfig { @Bean public DefaultKaptcha getDefaultKaptcha() { DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); Properties properties = new Properties(); properties.setProperty("kaptcha.border", "yes"); properties.setProperty("kaptcha.border.color", "105,179,90"); properties.setProperty("kaptcha.textproducer.font.color", "blue"); properties.setProperty("kaptcha.image.width", "110"); properties.setProperty("kaptcha.image.height", "40"); properties.setProperty("kaptcha.textproducer.font.size", "30"); properties.setProperty("kaptcha.session.key", "code"); properties.setProperty("kaptcha.textproducer.char.length", "4"); properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑"); Config config = new Config(properties); defaultKaptcha.setConfig(config); return defaultKaptcha; } }
这样kaptcha的样式和颜色字体等就设置好了,接着就是生成图形上的字符,同时通过二进制流的形式把生成的图片返回给前端。
代码如下:
package com.example.demo.controller; import com.google.code.kaptcha.impl.DefaultKaptcha; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.imageio.ImageIO; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.awt.image.BufferedImage; /** * <p> * 用户信息表 前端控制器 * </p> * * @author hacker */ @RestController @RequestMapping("/api/") public class UserInfoController { @Autowired private DefaultKaptcha captchaProducer; @GetMapping("/getVerifyCode") public void getVerifyCode(HttpServletRequest request, HttpServletResponse response) throws Exception { String createText = captchaProducer.createText(); request.getSession().setAttribute("verifyCode", createText); response.setHeader("Cache-Control", "no-store"); response.setHeader("Pragma", "no-cache"); response.setDateHeader("Expires", 0); response.setContentType("image/jpeg"); BufferedImage challenge = captchaProducer.createImage(createText); ServletOutputStream outputStream = response.getOutputStream(); ImageIO.write(challenge, "jpg", outputStream); try { outputStream.flush(); } finally { outputStream.close(); } } }
这样我们就可以用GET方式获取到生成的图形验证码了。
为了能在浏览器里显示我们这里采用thymeleaf模板。
在pom.xml文件中引入thymeleaf依赖如下:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
之后在templates文件夹下新建一个index.html文件,代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>CAPTCHA</title> <script type="text/javascript"> function refresh() { document.getElementById('captcha_img').src = "/api/getVerifyCode?" + Math.random(); } </script> </head> <body> <div> <img id="captcha_img" alt="点击更换" title="点击更换" onclick="refresh()" src="/api/getVerifyCode"/> </div> </body> </html>
这样一个简单前端显示图形验证码就做好了,之后我们输入http://localhost:8090/,就可以访问了,8090换成自己对应的端口。
图形验证码
点击图片可以切换图形验证码。至此,图形验证码功能结束!
如果觉得文章对你有帮助,欢迎关注,点赞,转发,评论!后续文章会介绍如何通过程序识别今天生成的图形验证码,感兴趣的同学,可以持续关注!
相关阅读:
基于spring boot快速搭建Java服务器
Spring Boot项目部署简单方便的Shell脚本
推荐一款Spring Boot中非常好用的插件
网页设计中,尤其表单填写提交过程中,为防止机器自动登录,很多网页都采用验证码技术,允许用户输入而尽量避免自动登录。验证码实现的方法有很多,PHP绘图技术可以在服务端生成验证码并发送客户端,HTML5技术下可以使用canvas与JS脚本实现在客户端浏览器自动生成验证码。本文给出JS+Canvas验证码的解决措施,所制作验证码实现效果如下图所示:
验证码实现效果动态图
本例验证码的实现主要包括验证码字符串的生成、背景干扰点实现及干扰直线的生成三部分。最终通过canvas绘图技术将生成的验证码字符串、背景及干扰直线显示到画布上。主要涉及技术或知识点包括canvas绘图技术、数组、鼠标点击事件、随机函数等。以下从验证字符串、背景干扰点及干扰直线三方面对实现过程进行说明。
验证字符串部分主要借助数组存储验证码所有字符,通过调用Math对象的随机函数获取数组下标,并通过数组下表读取数组元素,将读取的数组元素组装成完整字符串。其实现核心代码如下:
验证字符串获取核心代码
如上图所示,本例验证码字符包括数字与大写字母,getCode函数返回值即为4位验证码字符串。
背景干扰点可以直接使用canvas对应的绘图方法进行绘制,本例为简化开发过程,降低难度直接使用drawImage绘图方式加载背景图片,实现干扰点效果。背景图片如下:
背景干扰点图片
通过调用drawImage方法,指定截取的坐标位置参数,可实现背景干扰点的动态变化效果,背景干扰点实现核心代码如下:
背景干扰点实现代码
其中getXsize与getYsize为获取绘图截取背景图片的坐标位置,通过使用随机函数实现从背景图片不同位置截取进行绘图输出。
干扰直线实现较为简单,直接通过JS提供的moveTo与lineTo方法完成直线的绘制,本例绘制了两条直线,一条为黑色干扰线,一条为白色干扰线。在绘制过程两端点需要使用Math随机函数生成符合条件随机坐标。干扰直线相关实现代码如下:
干扰直线实现核心代码
干扰直线实现核心代码如上图,其中getLsize方法主要用于获取随机端点Y轴坐标值。strokeStyle主要用于设置绘图直线的颜色。
验证码的显示输出主要使用fillText()方法在canvas指定位置进行文字输出,本例使用第三方ttf字体,因此在HTML页面中对字体进行了加载。验证码显示输出实现代码如下:
验证码绘制
验证码显示输出核心代码如上图所示,其中myfont为加载的第三方字体。
绘图基础部分主要包括前端canvas元素的布局等。包括属性的设置,js部分元素的获取及属性设置等。
我们一般接触的验证码,都可以点击图片实现验证码的刷新,因此本例为canvas标记添加了onclick事件,将所有验证码生成的代码封装到showCode()函数中,通过调用showCode函数实现验证码的刷新。本例完整JS脚本部分代码如下:
JS实现脚本代码
本头条号长期关注编程资讯分享;编程课程、素材、代码分享及编程培训。如果您对以上方面有兴趣或代码错误、建议与意见,可以联系作者,共同探讨。期待大家关注!如需案例完整代码请关注并私信,往期前端设计文章链接如下:
近有同事在调研微信小程序,准备把我们的 landing page(LP)页面,迁移到小程序里,提高用户体验,提升转化率。
在LP里,遇到个很常见的问题,用户通过手机号注册,发送短信验证码需要防刷,目前在 h5 上使用的是 图形验证码+极验。一上来,就遇到了图形验证码的问题。小程序和 web 开发不同,不会 自动处理 http 请求的 cookie。
通常在 web 上,我们会把图形验证码存储到用户 session 里,然后在发送短信的接口,判断用户提交的图形验证码和 session 里的值是否相等,这里依赖浏览器自动会处理 cookie 的读写来实现的。但是小程序里,需要开发者主动来管理 cookie 等,并且在图片请求中,也 不能 主动设置cookie,导致之前 web 上的图形验证码完全失效。
在网上发现提到小程序里的图形验证码实现的文章很少,就有一篇这个 wechat-captcha ,但是作者这是纯前端用 canvas 来绘制的图形验证码,显然,图形验证码的生成,只能放在 server 端,这种方案,就需要有一种很好的方式,来讲server端生成的图形验证码的值,传递到前端来。没想到有什么方案,能从server端比较稳妥的传递图形验证码的值到小程序里,只能看看其他大厂是怎么做的了。
server 返回图片base64编码
同事发现饿了么的小程序里,是有图形验证码的,那就先来看看饿了么的同学是怎么实现的呢。经过抓包,很明显能看到饿了么的图片验证码请求,是通过 js 来发起的,server 端返回的图形验证码的 base64 编码,没有继续看后续是怎么把 base64 编码渲染到出来的,但肯定是有办法将 base64 的图形验证码绘制到 canvas 上的。
其实这里是有个疑问的,在抓包的时候,发现在请求图形验证码的时(POST),并没有带上 cookie,也就是说,饿了么并没有用 cookie-session 来存储某个手机号对应的图形验证码;并且用户的手机号,拼在了请求的 url 里,似乎在server端是通过其他方式,来存储的手机号和图形验证码的关联。
我不太理解的是,既然用户手机号已经放在请求的 path 里了,为什么要使用 POST 来单独请求图验的 base64 编码,再渲染到 canvas 上,为什么不直接拼一个 GET 的 url,同样把手机号放进去,然后接口直接输出二进制的图片数据,这样就可以直接把 url 赋值给小程序的 image 组件了。
饿了么抓包如下(响应中的 captcha_image 字段就是 png 图片的 base64编码):
使用 WebView
然后又看了下美团的小程序,直接没用图形验证码,而是用的类似极验的滑块。猜想也是使用了 canvas 之类的技术来实现的,抓包才发现,原来是用的 web-view组件来引用的 html 页面。刚重新抓包过程中,虽然后端响应接口确实返回了一个 h5 的滑块页面URL,但是没看到有加载这个页面,看来美团也 没有 用 web-view 来加载 h5。
美团抓包如下:
*请认真填写需求信息,我们会在24小时内与您取得联系。