前言
行为验证码(滑动拼图、点选文字),前后端(java)交互 完整示例 附源码
前提
安装Redis https://blog.csdn.net/javanbme/article/details/111591083
后端完整示例
1. 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.anji-plus</groupId>
<artifactId>spring-boot-starter-captcha</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.70</version>
</dependency>
2. 添加yml配置
application.yml
server:
port: 8080
#指定滑动验证码类型 滑动:blockpuzzle 点选:clickword
spring:
profiles:
active: blockpuzzle
application-blockpuzzle.yml
#滑动验证码配置
aj:
captcha:
jigsaw: classpath:images/jigsaw #底图路径,不配置将使用默认图片
cache-type: redis # 缓存local/redis...
cache-number: 1000 # 缓存的阈值,达到这个值,清除缓存
timing-clear: 300 # 定时清除过期缓存(单位秒),设置为0代表不执行
type: blockpuzzle # 验证码类型
water-mark: #水印文字
slip-offset: 5 # 校验滑动拼图允许误差偏移量(默认5像素)
aes-status: true # aes加密坐标开启或者禁用(true|false)
interference-options: 2 # 滑动干扰项(0/1/2)
history-data-clear-enable: true #历史数据是否清除
req-frequency-limit-enable: true # 接口请求次数一分钟限制是否开启 true|false
req-get-lock-limit: 5 # 验证失败5次,get接口锁定
req-get-lock-seconds: 300 # 验证失败后,锁定时间间隔,s
req-get-minute-limit: 20 # get接口一分钟内请求数限制
req-check-minute-limit: 20 # check接口一分钟内请求数限制
# redis配置
spring:
redis:
host: localhost
port: 6379
password:
timeout: 5000
application-clickword.yml
#点选文字验证码配置
aj:
captcha:
jigsaw: classpath:images/jigsaw
pic-click: classpath:images/pic-click #底图路径,不配置将使用默认图片
cache-type: redis # 缓存local/redis...
cache-number: 1000 # 缓存的阈值,达到这个值,清除缓存
timing-clear: 300 # 定时清除过期缓存(单位秒),设置为0代表不执行
type: clickword
slip-offset: 5 # 校验滑动拼图允许误差偏移量(默认5像素)
aes-status: true # aes加密坐标开启或者禁用(true|false)
# https://tool.chinaz.com/tools/unicode.aspx 中文转Unicode
font-type: \u5b8b\u4f53 # 汉字统一使用Unicode,保证程序通过@value读取到是中文,可通过这个在线转换
water-mark: #水印文字
interference-options: 2 # 滑动干扰项(0/1/2)
history-data-clear-enable: true #历史数据是否清除
req-frequency-limit-enable: true # 接口请求次数一分钟限制是否开启 true|false
req-get-lock-limit: 5 # 验证失败5次,get接口锁定
req-get-lock-seconds: 300 # 验证失败后,锁定时间间隔,s
req-get-minute-limit: 20 # get接口一分钟内请求数限制
req-check-minute-limit: 20 # check接口一分钟内请求数限制
# redis配置
spring:
redis:
host: localhost
port: 6379
password:
timeout: 5000
3. 验证码缓存实现类
@Service
public class CaptchaCacheServiceRedisImpl implements CaptchaCacheService {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Override
public void set(String key, String value, long expiresInSeconds) {
stringRedisTemplate.opsForValue().set(key, value, expiresInSeconds, TimeUnit.SECONDS);
}
@Override
public boolean exists(String key) {
return stringRedisTemplate.hasKey(key);
}
@Override
public void delete(String key) {
stringRedisTemplate.delete(key);
}
@Override
public String get(String key) {
return stringRedisTemplate.opsForValue().get(key);
}
@Override
public Long increment(String key, long val) {
return stringRedisTemplate.opsForValue().increment(key,val);
}
@Override
public String type() {
return "redis";
}
}
4. 跨域配置(本地启动)
@WebFilter(filterName = "CorsFilter ")
@Configuration
public class CorsFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws ServletException, IOException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request = (HttpServletRequest) servletRequest;
response.setContentType("application/json; charset=utf-8");
response.setCharacterEncoding("UTF-8");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Methods", "POST, GET,PUT, OPTIONS, DELETE");//http请求方式
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, token");
filterChain.doFilter(request, response);
}
@Override
public void destroy() {
}
}
5. META-INF/service
创建文件 com.anji.captcha.service.CaptchaCacheService
内容 添加实现类的全限定名 com.javanbme.captcha.service.impl.CaptchaCacheServiceRedisImpl (填写你自己的类路径)
6. controller
@Slf4j
@RestController
@RequestMapping("/auth")
public class LoginController {
@Autowired
private CaptchaService captchaService;
@PostMapping("/get")
public ResponseModel get(@RequestBody CaptchaVO captchaVO) {
return captchaService.get(captchaVO);
}
@PostMapping("/check")
public ResponseModel check(@RequestBody CaptchaVO captchaVO) {
ResponseModel check = captchaService.check(captchaVO);
//repCode 0000 无异常,代表成功
//repCode 9999 服务器内部异常
//repCode 0011 参数不能为空
//repCode 6110 验证码已失效,请重新获取
//repCode 6111 验证失败
//repCode 6112 获取验证码失败,请联系管理员
log.info("code={},msg={}",check.getRepCode(),check.getRepMsg());
return check;
}
}
7. 项目结构
前端示例
1. 内容有点多 贴出部分
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"/>
<title>verify插件demo</title>
<link rel="stylesheet" type="text/css" href="css/verify.css">
<script>
(function () {
if (!window.Promise) {
document.writeln('<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.1.1/es6-promise.min.js"><' + '/' + 'script>');
}
})();
</script>
<style>
.btn{
border: none;
outline: none;
width: 300px;
height: 40px;
line-height: 40px;
text-align: center;
cursor: pointer;
background-color: #409EFF;
color: #fff;
font-size: 16px;
letter-spacing: 1em;
}
</style>
</head>
<body>
<div class="box">
<h1>verify---anji</h1>
<p>前后端联合交互的验证码插件</p>
<br><br>
<h3>滑动嵌入式(slider-embed)</h3>
<div id="mpanel1" >
</div>
<h3>滑动弹出式(slider-popup)</h3>
<button class="btn" id='btn'>点击我</button>
<div id="mpanel2" style="margin-top:50px;">
</div>
</div>
<script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/jquery/1.9.1/jquery.js" ></script>
<script src="./js/crypto-js.js"></script>
<script src="./js/ase.js"></script>
<script src="js/verify.js" ></script>
<script>
// 初始化验证码 嵌入式
$('#mpanel1').slideVerify({
baseUrl:'http://localhost:8080', //local-spring-boot;
mode:'fixed',
imgSize : { //图片的大小对象
width: '400px',
height: '200px',
},
barSize:{
width: '400px',
height: '40px',
},
ready : function() { //加载完毕的回调
},
success : function(params) { //成功的回调
// 返回的二次验证参数 合并到验证通过之后的逻辑 参数中回传服务器
console.log(params,"params");
},
error : function() { //失败的回调
}
});
// // 初始化验证码 弹出式
$('#mpanel2').slideVerify({
baseUrl:'http://localhost:8080', //服务器请求地址, 默认地址为安吉服务器;
mode:'pop', //展示模式
containerId:'btn',//pop模式 必填 被点击之后出现行为验证码的元素id
imgSize : { //图片的大小对象,有默认值{ width: '310px',height: '155px'},可省略
width: '400px',
height: '200px',
},
barSize:{ //下方滑块的大小对象,有默认值{ width: '310px',height: '50px'},可省略
width: '400px',
height: '40px',
},
beforeCheck:function(){ //检验参数合法性的函数 mode ="pop"有效
var flag = true;
//实现: 参数合法性的判断逻辑, 返回一个boolean值
return flag
},
ready : function() {}, //加载完毕的回调
success : function(params) { //成功的回调
// params为返回的二次验证参数 需要在接下来的实现逻辑回传服务器
// 例如: login($.extend({}, params))
},
error : function() {} //失败的回调
});
</script>
</body>
</html>
2. 项目结构
最终效果
前后端示例源码
https://download.csdn.net/download/javanbme/15610755