验证码的作用是防止恶意破解密码、刷票、论坛灌水、刷页等。
如下是一个实际例子:
image.png
而Kaptcha则是生成这样的验证码图片的一个功能强大的工具包。
然后开始说这个Kaptcha要怎么使用。
导包
com.github.axet
kaptcha
0.0.9
添加配置
package io.renren.config;
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 Mark [email protected]
*/
@Configuration
public class KaptchaConfig {
@Bean
public DefaultKaptcha producer() {
Properties properties = new Properties();
properties.put("kaptcha.border", "no");
properties.put("kaptcha.textproducer.font.color", "black");
properties.put("kaptcha.textproducer.char.space", "6");
properties.put("kaptcha.textproducer.font.names", "Arial,Courier,cmr10,宋体,楷体,微软雅黑");
Config config = new Config(properties);
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}
然后上面的几个配置自己看着写。这个kaptcha有多种配置可以改的,我贴出来:
kaptcha可选参数
可选参数2
反正我用起来也没那么麻烦,其实默认配置差不多就满足了,自己看心意调吧。
在接口中使用
以上两步配置就完了,接下来该使用了。
其实就是把它配置成一个可以前端访问的接口了。
存session中
@Autowired
private Producer producer;
@GetMapping("kaptcha.jpg")
public void kaptcha(HttpServletResponse response,HttpServletRequest request) throws ServletException,IOException{
response.setHeader("Cache-Control", "no-store,no-cache");
response.setContentType("image/jpeg");
//生成文字验证码
String text=producer.createText();
//生成图片验证码
BufferedImage image=producer.createImage(text);
//保存验证码到session
request.getSession().setAttribute(Constants.KAPTCHA_SESSION_KEY, text);
ServletOutputStream out=response.getOutputStream();
ImageIO.write(image, "jpg", out);
//用到IO工具包控制开关
IOUtils.closeQuietly(out);
}
存数据库
存session就不多说了,但是我使用的时候是存数据库的,个人感觉存数据库可以灵活设置过期时间。(好吧,我承认这个做法是当时没想到session)。反正现在是实现了,所以也记录下来吧。
因为存数据库所以肯定要先建表:
表结构
如图,很简单的表结构:uuid是主键,code是验证码。expire_time是过期时间。
然后每次生成验证码,需要一个参数(说是uuid其实用的时候就是一个id的作用)。会将这个uuid当做表的主键,然后code和过期时间一起存到数据库。
在登录的时候先做校验,判断这个uuid的code和输入的验证码是否一样,是的话验证成功,并且删除这条记录。不是的话返回验证码错误。
大概逻辑就是这样,我一步步贴代码:
这个是将验证码保存到数据库和校验验证码的两个方法
@Autowired
private Producer producer;
/**
* 生成验证码并且将这条记录保存到数据库
*/
@Override
public BufferedImage getCaptcha(String uuid) {
if(StringUtils.isBlank(uuid)){
throw new RRException("uuid不能为空");
}
//生成文字验证码
String code = producer.createText();
//这里是生成实体,然后存入数据库,看逻辑就行,别原封不动用代码
SysCaptchaEntity captchaEntity = new SysCaptchaEntity();
captchaEntity.setUuid(uuid);
captchaEntity.setCode(code);
//3分钟后过期.这个用到了自己封装的日期处理方法
captchaEntity.setExpireTime(DateUtils.addDateMinutes(new Date(), 3));
this.save(captchaEntity);
return producer.createImage(code);
}
/**
* 验证验证码是否正确
*/
@Override
public boolean validate(String uuid, String code) {
SysCaptchaEntity captchaEntity = this.getOne(new QueryWrapper().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;
}
这个是正式调用生成验证码的方法:
/**
* 验证码
*/
@ApiOperation("获取验证码")
@RequestMapping("kaptcha.jpg")
public void kaptcha(HttpServletResponse response, @ApiParam(name="uuid",value="随机字符串") 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);
}
这个是在登录的时候验证验证码的两行代码:
boolean captcha = sysCaptchaService.validate(form.getUuid(), form.getCaptcha());
if(!captcha){
return R.error("验证码不正确");
}
至此,这个生成验证码的功能完成了,顺便附上截图:
postman自测
网页测试
本篇笔记就到这里,如果稍微帮到你了记得点个喜欢点个关注。也祝大家工作顺顺利利,生活愉快!