一 、为啥要使用验证码
验证码(CAPTCHA) 是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机还是人的公共全自动程序。可以防止:恶意破解密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试,实际上用验证码是现在很多网站通行的方式,我们利用比较简易的方式实现了这个功能。今天给大家介绍一下kaptcha的和springboot一起使用的简单例子,kaptcha是谷歌的开源的工具类,本文使用的是第三方封装的jar包,由于是前后端分离项目,不能将验证码存在session作用域中,同时也是考虑到安全和跨域的问题,本文还需将验证码存在数据库中用于登录的时候的校验。
二、使用
1. 引用maven坐标依赖
<dependency>
<groupId>com.github.axet</groupId>
<artifactId>kaptcha</artifactId>
<version>0.0.9</version>
</dependency>
2.验证码数据库表实现
CREATE TABLE `sys_captcha` (
`uuid` char(36) NOT NULL COMMENT 'uuid',
`code` varchar(6) NOT NULL COMMENT '验证码',
`expire_time` datetime DEFAULT NULL COMMENT '过期时间',
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统验证码';
3.生成和校验代码的核心代码
service层
// 将验证码生成的bean注入进来
@Autowired
private Producer producer;
/**
* 验证码生成
* @param uuid
* @return
*/
@Override
public BufferedImage getCaptcha(String uuid) {
if(StringUtils.isBlank(uuid)){
throw new RRException("uuid不能为空");
}
//1. 生成文字验证码
String code = producer.createText();
SysCaptchaEntity captchaEntity = new SysCaptchaEntity();
captchaEntity.setUuid(uuid);
captchaEntity.setCode(code);
//2. 设置5分钟后过期
captchaEntity.setExpireTime(DateUtils.addDateMinutes(new Date(), 5));
this.save(captchaEntity);
return producer.createImage(code);
}
/**
* 验证码校验
* @param uuid uuid
* @param code 验证码
* @return
*/
@Override
public boolean validate(String uuid, String code) {
SysCaptchaEntity captchaEntity = this.getOne(new QueryWrapper<SysCaptchaEntity>().eq("uuid", uuid));
if(captchaEntity == null){
return false;
}
//删除验证码,不管这次校验是否成功这个验证码都失效了,验证码都是一次性的,所以可以删除掉了,减少垃圾数据
this.removeById(uuid);
if(captchaEntity.getCode().equalsIgnoreCase(code) && captchaEntity.getExpireTime().getTime() >= System.currentTimeMillis()){
return true;
}
return false;
}
Controller层
/**
* 验证码
*/
@GetMapping("captcha.jpg")
public void captcha(HttpServletResponse response, String uuid)throws IOException {
response.setHeader("Cache-Control", "no-store, no-cache");
response.setContentType("image/jpeg");
//获取图片验证码
BufferedImage image = sysCaptchaService.getCaptcha(uuid);
ServletOutputStream out = response.getOutputStream();
ImageIO.write(image, "jpg", out);
IOUtils.closeQuietly(out);
}
具体的代码可以参考:
https://github.com/Dr-Water/ratel-fast/blob/master/src/main/java/com/ratel/fast/modules/sys/service/impl/SysCaptchaServiceImpl.java
4. 使用思路
- 前端每次请求新的验证码的时候都会带一个uuid,每次的uuid都不一样
- 后端使用这个uuid作为这个验证码的唯一标识生成一个验证码保存在数据库中,并将验证码图片返回给前端
- 前端进行登录认证的再次将生成验证码的uuid传到后端,后端根据这个uuid去查询数据库,并校验验证码是否正确
三、一些优秀的参考链接
https://www.jianshu.com/p/a3525990cd82
Javaweb—谷歌kaptcha图片验证码的使用
springboot整合kaptcha验证码