AJ-Captcha行为验证码,包含滑动拼图、文字点选两种方式,UI支持弹出和嵌入两种方式。后端提供Java、Golang实现,前端提供了php、angular、html、vue、uni-app、flutter、android、ios等代码示例。

交互流程

后端接入

引入依赖

1、需要Redis依赖
2、需要Hutool依赖

 <!-- 滑动验证码 -->
<dependency>
    <groupId>com.anji-plus</groupId>
    <artifactId>captcha-spring-boot-starter</artifactId>
    <version>1.4.0</version>
</dependency>

yml配置

# 验证码配置
aj:
  captcha:
    # 滑动验证,底图路径,不配置将使用默认图片;以 classpath: 开头,取 resource 目录下路径
    jigsaw: classpath:captcha/jigsaw
    # 滑动验证,底图路径,不配置将使用默认图片;以 classpath: 开头,取 resource 目录下路径
    pic-click: classpath:captcha/pic-click
    # 缓存 local/redis...
    cache-type: redis
    # local 缓存的阈值,达到这个值,清除缓存
    cache-number: 1000
    # local定时清除过期缓存(单位秒),设置为0代表不执行
    timing-clear: 180
    # 验证码类型 default两种都实例化。 blockPuzzle: 滑块拼图  clickWord: 文字点选
    type: blockPuzzle
    # 右下角水印文字(我的水印),可使用 https://tool.chinaz.com/tools/unicode.aspx 中文转 Unicode,Linux 可能需要转 unicode
    water-mark: 小飞博客
    # 滑动干扰项(0/1/2)
    interference-options: 0
    # 接口请求次数一分钟限制是否开启 true|false
    req-frequency-limit-enable: true
    # 验证失败5次,get接口锁定
    req-get-lock-limit: 15
    # 验证失败后,锁定时间间隔
    req-get-lock-seconds: 1000
    # get 接口一分钟内请求数限制
    req-get-minute-limit: 30
    # check 接口一分钟内请求数限制
    req-check-minute-limit: 60
    # verify 接口一分钟内请求数限制
    req-verify-minute-limit: 60

将源码图片文件目录复制到自己项目

添加实现类

import com.anji.captcha.service.CaptchaCacheService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;

/**
 *  基于 Redis 实现验证码的存储
 *
 * @author xiaofei
 */
@Service
public class RedisCaptchaServiceImpl implements CaptchaCacheService {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }
    @Override
    public String type() {
        return "redis";
    }
    @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 Boolean.TRUE.equals(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);
    }
}

添加实现类指向

1、目录文件:META-INF/services/com.anji.captcha.service.CaptchaCacheService
2、文件里面指向自己实现类:com.xxx.service.impl.RedisCaptchaServiceImpl

重写验证码Controller

import cn.hutool.core.util.StrUtil;
import com.anji.captcha.model.common.ResponseModel;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import com.xffjs.common.constant.CommonConstant;
import com.xffjs.framework.web.controller.BaseController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import cn.hutool.extra.servlet.ServletUtil;

/**
 * 图片验证码
 *
 * @author xiaofei
 */
@Controller
@RequestMapping("/captcha")
public class CaptchaController extends BaseController {
    @Resource
    private CaptchaService captchaService;
    @PostMapping("/get")
    @ResponseBody
    public ResponseModel get(@RequestBody CaptchaVO data, HttpServletRequest request) {
        assert request.getRemoteHost() != null;
        data.setBrowserInfo(getRemoteId(request));
        return captchaService.get(data);
    }
    @PostMapping("/check")
    @ResponseBody
    public ResponseModel check(@RequestBody CaptchaVO data, HttpServletRequest request) {
        data.setBrowserInfo(getRemoteId(request));
        return captchaService.check(data);
    }
    public static String getRemoteId(HttpServletRequest request) {
        String ip = ServletUtil.getClientIP(request);
        String ua = request.getHeader("user-agent");
        if (StrUtil.isNotBlank(ip)) {
            return ip + ua;
        }
        return request.getRemoteAddr() + ua;
    }
}

二次验签

二次验签可以放在登录接口前面。

@PostMapping("/login")
public ResponseModel get(@RequestParam("captchaVerification") String captchaVerification) {
     CaptchaVO captchaVO = new CaptchaVO();
     captchaVO.setCaptchaVerification(captchaVerification);
     ResponseModel response = captchaService.verification(captchaVO);
     if(response.isSuccess() == false){
         // 验证码校验失败,返回信息告诉前端
         // repCode  0000  无异常,代表成功
         // repCode  9999  服务器内部异常
         // repCode  0011  参数不能为空
         // repCode  6110  验证码已失效,请重新获取
         // repCode  6111  验证失败
         // repCode  6112  获取验证码失败,请联系管理员
     }else{
         // 自己代码
     }
     return response;
 }

前端接入

这里前端我使用的是HTML方式。其他前端方式可以参考文档传送

1、引入css文件verify.css

2、按顺序引入js文件下js文件 jquery.min.js, crypto-js.js, ase.js, verify.js

3、在登录页面添加以下代码

<div id="content"></div>
//  mode="pop"模式配置点击
<button id="btn">点击出现验证码</button>

5、script脚本

<script>
    $('#content').slideVerify({
        baseUrl:'https://127.0.0.1:80/captcha',  //服务器请求地址;
        containerId:'btn',//pop模式 必填 被点击之后出现行为验证码的元素id
        mode:'pop',     //展示模式
        imgSize : {       //图片的大小对象,有默认值{ width: '310px',height: '155px'},可省略
            width: '400px',
            height: '200px',
        },
        barSize:{          //下方滑块的大小对象,有默认值{ width: '310px',height: '50px'},可省略
            width: '400px',
            height: '40px',
        },
        beforeCheck:function(){  //检验参数合法性的函数  mode ="pop"有效
            let flag = true;
            //实现: 参数合法性的判断逻辑, 返回一个boolean值
            return flag
        },
        ready : function() {},  //加载完毕的回调
        success : function(params) { //成功的回调
            // params为返回的二次验证参数 需要在接下来的实现逻辑回传服务器
            例如: login($.extend({}, params))
        },
        error : function() {}        //失败的回调
    });
</script>

测试效果