官网:https://ajcaptcha.beliefteam.cn/captcha-doc/
行为验证码采用嵌入式集成方式,接入方便,安全,高效。抛弃了传统字符型验证码展示-填写字符-比对答案的流程,采用验证码展示-采集用户行为-分析用户行为流程,用户只需要产生指定的行为轨迹,不需要键盘手动输入,极大优化了传统验证码用户体验不佳的问题;同时,快速、准确的返回人机判定结果。目前对外提供两种类型的验证码,其中包含滑动拼图、文字点选。
后端基于Java实现,提供纯Java.jar和SpringBoot Starter。前端提供了Android、iOS、Futter、Uni-App、ReactNative、Vue、Angular、Html、Php等多端示例。
使用:
1 后端
1引入依赖
<dependency>
<groupId>com.anji-plus</groupId>
<artifactId>spring-boot-starter-captcha</artifactId>
<version>1.3.0</version>
</dependency>
2 配置
简单配置
# 滑块验证码
aj:
captcha:
# blockPuzzle滑块 clickWord文字点选 default默认两者都实例化
type: blockPuzzle
# 右下角显示字
water-mark: liusu
# 校验滑动拼图允许误差偏移量(默认5像素)
slip-offset: 5
# aes加密坐标开启或者禁用(true|false)
aes-status: true
# 滑动干扰项(0/1/2)
interference-options: 2
复杂配置:
# 滑动验证,底图路径,不配置将使用默认图片
# 支持全路径
# 支持项目路径,以classpath:开头,取resource目录下路径,例:classpath:images/jigsaw
aj.captcha.jigsaw=classpath:images/jigsaw
#滑动验证,底图路径,不配置将使用默认图片
##支持全路径
# 支持项目路径,以classpath:开头,取resource目录下路径,例:classpath:images/pic-click
aj.captcha.pic-click=classpath:images/pic-click
# 对于分布式部署的应用,我们建议应用自己实现CaptchaCacheService,比如用Redis或者memcache,
# 参考CaptchaCacheServiceRedisImpl.java
# 如果应用是单点的,也没有使用redis,那默认使用内存。
# 内存缓存只适合单节点部署的应用,否则验证码生产与验证在节点之间信息不同步,导致失败。
# !!! 注意啦,如果应用有使用spring-boot-starter-data-redis,
# 请打开CaptchaCacheServiceRedisImpl.java注释。
# redis -----> SPI: 在resources目录新建META-INF.services文件夹(两层),参考当前服务resources。
# 缓存local/redis...
aj.captcha.cache-type=local
# local缓存的阈值,达到这个值,清除缓存
#aj.captcha.cache-number=1000
# local定时清除过期缓存(单位秒),设置为0代表不执行
#aj.captcha.timing-clear=180
#spring.redis.host=10.108.11.46
#spring.redis.port=6379
#spring.redis.password=
#spring.redis.database=2
#spring.redis.timeout=6000
# 验证码类型default两种都实例化。
aj.captcha.type=default
# 汉字统一使用Unicode,保证程序通过@value读取到是中文,可通过这个在线转换;yml格式不需要转换
# https://tool.chinaz.com/tools/unicode.aspx 中文转Unicode
# 右下角水印文字(我的水印)
aj.captcha.water-mark=\u6211\u7684\u6c34\u5370
# 右下角水印字体(不配置时,默认使用文泉驿正黑)
# 由于宋体等涉及到版权,我们jar中内置了开源字体【文泉驿正黑】
# 方式一:直接配置OS层的现有的字体名称,比如:宋体
# 方式二:自定义特定字体,请将字体放到工程resources下fonts文件夹,支持ttf\ttc\otf字体
# aj.captcha.water-font=WenQuanZhengHei.ttf
# 点选文字验证码的文字字体(文泉驿正黑)
# aj.captcha.font-type=WenQuanZhengHei.ttf
# 校验滑动拼图允许误差偏移量(默认5像素)
aj.captcha.slip-offset=5
# aes加密坐标开启或者禁用(true|false)
aj.captcha.aes-status=true
# 滑动干扰项(0/1/2)
aj.captcha.interference-options=2
#点选字体样式 默认Font.BOLD
aj.captcha.font-style=1
#点选字体字体大小
aj.captcha.font-size=25
#点选文字个数,存在问题,暂不支持修改
#aj.captcha.click-word-count=4
aj.captcha.history-data-clear-enable=false
# 接口请求次数一分钟限制是否开启 true|false
aj.captcha.req-frequency-limit-enable=false
# 验证失败5次,get接口锁定
aj.captcha.req-get-lock-limit=5
# 验证失败后,锁定时间间隔,s
aj.captcha.req-get-lock-seconds=360
# get接口一分钟内请求数限制
aj.captcha.req-get-minute-limit=30
# check接口一分钟内请求数限制
aj.captcha.req-check-minute-limit=60
# verify接口一分钟内请求数限制
aj.captcha.req-verify-minute-limit=60
3 使用
获取验证码接口:http://:/captcha/get
请求参数:
{
"captchaType": "blockPuzzle", //验证码类型 clickWord
"clientUid": "唯一标识" //客户端UI组件id,组件初始化时设置一次,UUID(非必传参数)
}
响应参数:
"repCode": "0000",
"repData": {
"originalImageBase64": "底图base64",
"point": { //默认不返回的,校验的就是该坐标信息,允许误差范围
"x": 205,
"y": 5
},
"jigsawImageBase64": "滑块图base64",
"token": "71dd26999e314f9abb0c635336976635", //一次校验唯一标识
"secretKey": "16位随机字符串", //aes秘钥,开关控制,前端根据此值决定是否加密
"result": false,
"opAdmin": false
},
"success": true,
"error": false
}
核对验证码接口接口:http://:/captcha/check
请求参数:
{
"captchaType": "blockPuzzle",
"pointJson": "QxIVdlJoWUi04iM+65hTow==", //aes加密坐标信息
"token": "71dd26999e314f9abb0c635336976635" //get请求返回的token
}
响应参数
{
"repCode": "0000",
"repData": {
"captchaType": "blockPuzzle",
"token": "71dd26999e314f9abb0c635336976635",
"result": true,
"opAdmin": false
},
"success": true,
"error": false
}
2 前端
前端使用的是vue,注意一定要保证和后端java版本一致。
1 复制view/vue/src/components/verifition文件夹,到自己工程对应目录下,在登录页面插入如下代码
2 安装请求和加密依赖
npm install axios crypto-js -S
//request.js
import axios from 'axios'
import { MessageBox, Message } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'
// create an axios instance
const service = axios.create({
baseURL:"/web", // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests
timeout: 5000 // request timeout
})
// request interceptor
service.interceptors.request.use(
config => {
// do something before request is sent
config.headers['Content-Type']='application/json;'
if (store.getters.token) {
// let each request carry token
// ['X-Token'] is a custom headers key
// please modify it according to the actual situation
config.headers['X-Token'] = getToken()
}
return config
},
error => {
// do something with request error
console.log(error) // for debug
return Promise.reject(error)
}
)
// response interceptor
service.interceptors.response.use(
response => {
const res = response.data
return res
},
)
export default service
3 使用
<template>
<div>
<Verify
@success="success"
mode="pop"
captchaType="blockPuzzle"
:imgSize="{ width: '330px', height: '155px' }"
ref="verify"
></Verify>
//mode="pop"模式
<button @click="useVerify">调用验证组件</button>
</div>
</template>
<script>
import Verify from '@/components/verifition/Verify'
import requestWeb from '@/utils/requestWeb'
export default {
name: 'index',
components:{
Verify
},
methods:{
async webget(){
let data={"captchaType":"blockPuzzle","clientUid":"slider-bcd6b53b-5516-478b-8854-1909e00d686f","ts":1668070762462}
let req=await requestWeb({
url: '/captcha/get',
method: 'post',
data
}
)
console.log('req'+req)
},
success(params){
// params 返回的二次验证参数, 和登录参数一起回传给登录接口,方便后台进行二次验证
},
useVerify(){
this.$refs.verify.show()
}
}
}
</script>
<style scoped>
</style>
3 排除错误
1 Resolved [org.springframework.http.converter.HttpMessageNotReadableException: I/O error while reading input message; nested exception is org.apache.catalina.connector.ClientAbortException: java.io.EOFException: Unexpected EOF read on the socket]
错误原因:axios请求get/check为post请求且config.headers[‘Content-Type’]=‘application/json;’