Kaptcha
介绍
Kaptcha 是Google的⼀个⾼度可配置的实⽤验证码⽣成⼯具
https://code.google.com/archive/p/kaptcha
⽹上有很多⼈甚⾄公司基于Google的kaptcha进⾏了⼆次开发. 我们选择⼀个直接适配SpringBoot的开源项⽬
插件使用介绍
基于GitHub项目来做介绍
原理
验证码可以客⼾端⽣成, 也可以服务器⽣成. 对于普通的字符验证码, 后端通常分两部分.
⼀是⽣成验证码内容, 根据验证码内容和⼲扰项等, ⽣成图⽚, 返回给客⼾端
⼆是把验证码内容存储起来, 校验时取出来进⾏对⽐.
kaptcha插件选择把验证码存储在Session⾥.
引入依赖
<dependency>
<groupId>com.oopsguy.kaptcha</groupId>
<artifactId>kaptcha-spring-boot-starter</artifactId>
<version>1.0.0-beta-2</version>
</dependency>
生成验证码
该插件提供了两种⽅式⽣成验证码
-
通过代码来⽣成(参考⽂档: https://github.com/oopsguy/kaptcha-spring-boot/blob/master/README_zh-CN.md, 不再介绍)
-
仅通过配置⽂件来⽣成验证码(推荐)
部分详细配置
配置项 | 配置说明 | 默认值 |
---|---|---|
border | 设置验证码边框的颜色 | “255,255,255,255” |
textProducerCharLength | 设置生成验证码的字符长度 | 4 |
textProducerCharSpace | 设置生成验证码时字符之间的间距 | 5 |
imageWidth | 设置验证码图片的宽度 | 200 |
imageHeight | 设置验证码图片的高度 | 50 |
noiseColor | 设置噪点的颜色 | “255,255,255,255” |
fontColor | 设置字体颜色 | “0,0,0,255” |
fontNames | 设置字体的名称,可以指定多个字体 | Arial, Courier |
textProducerImpl | 设置生成验证码文本的实现类 | 默认实现类 |
backgroundProducerImpl | 设置生成验证码背景的实现类 | 默认实现类 |
noiseProducerImpl | 设置生成验证码噪点的实现类 | 默认实现类 |
wordImpl | 设置生成验证码字符的实现类 | 默认实现类 |
obscurificatorImpl | 设置字符模糊处理的实现类 | 默认实现类 |
sessionKey | 设置存储验证码信息的 Session 键 | 默认值 |
sessionDate | 设置存储验证码创建时间的 Session 键 | 默认值 |
width | 设置验证码图片的宽度(同 imageWidth) | 200 |
height | 设置验证码图片的高度(同 imageHeight) | 50 |
验证码小项目
初始化前端代码
// success.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>验证成功页</title>
</head>
<body>
<h1>验证成功</h1>
</body>
</html>
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>验证码</title>
<style>
#inputCaptcha {
height: 30px;
vertical-align: middle;
}
#verificationCodeImg{
vertical-align: middle;
}
#checkCaptcha{
height: 40px;
width: 100px;
}
</style>
</head>
<body>
<h1>输入验证码</h1>
<div id="confirm">
<input type="text" name="inputCaptcha" id="inputCaptcha">
<img id="verificationCodeImg" src="/admin/captcha" style="cursor: pointer;" title="看不清?换一张" />
<input type="button" value="提交" id="checkCaptcha">
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script>
$("#verificationCodeImg").click(function(){
$(this).hide().attr('src', '/admin/captcha?dt=' + new Date().getTime()).fadeIn();
});
$("#checkCaptcha").click(function () {
alert("验证码校验");
});
</script>
</body>
</html>
约定前后端交互接口
需求分析
后端需要提供两个服务
-
⽣成验证码, 并返回验证码
-
校验验证码是否正确: 校验验证码是否正确
接口定义
-
生成验证码
请求
GET/admin/captcha
响应:图片
-
校验验证码是否正确
请求:/admin/check
POST /admin/check captcha=xn8d
captcha:用户输入的验证码
响应:
true
根据用户输入的验证码,校验验证码是否正确
完善前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>验证码</title>
<style>
#inputCaptcha {
height: 30px;
vertical-align: middle;
}
#verificationCodeImg{
vertical-align: middle;
}
#checkCaptcha{
height: 40px;
width: 100px;
}
</style>
</head>
<body>
<h1>输入验证码</h1>
<div id="confirm">
<input type="text" name="inputCaptcha" id="inputCaptcha">
<img id="verificationCodeImg" src="/admin/captcha" style="cursor: pointer;" title="看不清?换一张" />
<input type="button" value="提交" id="checkCaptcha">
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script>
$("#verificationCodeImg").click(function(){
$(this).hide().attr('src', '/admin/captcha?dt=' + new Date().getTime()).fadeIn();
});
$("#checkCaptcha").click(function () {
$.ajax({
type:"get",
url:"/admin/check",
data:{
inputCaptcha:$("#inputCaptcha").val()
},
success:function (result){
if (result){
// 页面跳转
location.href="success.html"
}else {
alert("验证码失败,请重试");
}
}
});
});
</script>
</body>
</html>
后端代码
package org.haobin.kaptcha;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpSession;
import java.util.Date;
@RestController
@RequestMapping("/admin")
public class KaptchaController {
public static final String KAPTCHA_SESSION_KEY = "KAPTCHA_SESSION_KEY";
public static final String KAPTCHA_SESSION_DATE = "KAPTCHA_SESSION_DATE";
public static final long TIME_OUT = 60 * 1000; // 1min 毫秒
/**
* 校验验证码是否正确
*
* @param inputCaptcha 用户输入的验证码
* @return
*/
@RequestMapping("/check")
public boolean check(String inputCaptcha, HttpSession session) {
// 1. 判断输入的验证码是否为空
if (!StringUtils.hasLength(inputCaptcha)) {
return false;
}
// 2. 获取生成的验证码
// 正确的验证码(生成验证码)
// 3. 比对 生成的验证码和输入的验证码是否一致
// 4. 确认验证码是否过期
String saveCaptcha = (String) session.getAttribute(KAPTCHA_SESSION_KEY);
Date saveCaptchaDate = (Date) session.getAttribute(KAPTCHA_SESSION_DATE);
// 不区分大小写
if (inputCaptcha.equalsIgnoreCase(saveCaptcha)) {
if (saveCaptchaDate != null || System.currentTimeMillis() - saveCaptchaDate.getTime() < TIME_OUT) {
return true;
}
}
return false;
}
}