当前位置:   article > 正文

Spring Boot集成AJ-Captcha实现滑动验证码功能

Spring Boot集成AJ-Captcha实现滑动验证码功能

1.AJ-Captcha介绍

行为验证码

采用嵌入式集成方式,接入方便,安全,高效。抛弃了传统字符型验证码展示-填写字符-比对答案的流程,采用验证码展示-采集用户行为-分析用户行为流程,用户只需要产生指定的行为轨迹,不需要键盘手动输入,极大优化了传统验证码用户体验不佳的问题;同时,快速、准确的返回人机判定结果

AJ-Captcha行为验证码

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

2.代码工程

pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>springboot-demo</artifactId>
  7. <groupId>com.et</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>Captcha</artifactId>
  12. <properties>
  13. <maven.compiler.source>8</maven.compiler.source>
  14. <maven.compiler.target>8</maven.compiler.target>
  15. </properties>
  16. <dependencies>
  17. <dependency>
  18. <groupId>org.springframework.boot</groupId>
  19. <artifactId>spring-boot-starter-web</artifactId>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.springframework.boot</groupId>
  23. <artifactId>spring-boot-autoconfigure</artifactId>
  24. </dependency>
  25. <dependency>
  26. <groupId>org.springframework.boot</groupId>
  27. <artifactId>spring-boot-starter-test</artifactId>
  28. <scope>test</scope>
  29. </dependency>
  30. <dependency>
  31. <groupId>com.anji-plus</groupId>
  32. <artifactId>spring-boot-starter-captcha</artifactId>
  33. <version>1.3.0</version>
  34. </dependency>
  35. <dependency>
  36. <groupId>org.springframework.boot</groupId>
  37. <artifactId>spring-boot-starter-data-redis</artifactId>
  38. </dependency>
  39. </dependencies>
  40. </project>

application.yaml

  1. spring.application.name=captcha-service
  2. server.port=8080
  3. # 滑动验证,底图路径,不配置将使用默认图片
  4. # 支持全路径
  5. # 支持项目路径,以classpath:开头,取resource目录下路径,例:classpath:images/jigsaw
  6. aj.captcha.jigsaw=classpath:images/jigsaw
  7. # 滑动验证,底图路径,不配置将使用默认图片
  8. # 支持全路径
  9. # 支持项目路径,以classpath:开头,取resource目录下路径,例:classpath:images/pic-click
  10. aj.captcha.pic-click=classpath:images/pic-click
  11. # 对于分布式部署的应用,我们建议应用自己实现CaptchaCacheService,比如用Redis或者memcache,
  12. # 参考CaptchaCacheServiceRedisImpl.java
  13. # 如果应用是单点的,也没有使用redis,那默认使用内存。
  14. # 内存缓存只适合单节点部署的应用,否则验证码生产与验证在节点之间信息不同步,导致失败。
  15. # !!!注意啦,如果应用有使用spring-boot-starter-data-redis,
  16. # 请打开CaptchaCacheServiceRedisImpl.java注释。
  17. # redis -----> SPI:在resources目录新建META-INF.services文件夹(两层),参考当前服务resources。
  18. # 缓存local/redis...
  19. aj.captcha.cache-type=local
  20. # local缓存的阈值,达到这个值,清除缓存
  21. #aj.captcha.cache-number=1000
  22. # local定时清除过期缓存(单位秒),设置为0代表不执行
  23. #aj.captcha.timing-clear=180
  24. #spring.redis.host=10.108.11.46
  25. #spring.redis.port=6379
  26. #spring.redis.password=
  27. #spring.redis.database=2
  28. #spring.redis.timeout=6000
  29. # 验证码类型default两种都实例化。
  30. aj.captcha.type=default
  31. # 汉字统一使用Unicode,保证程序通过@value读取到是中文,可通过这个在线转换
  32. # https://tool.chinaz.com/tools/unicode.aspx 中文转Unicode
  33. # 右下角水印文字(我的水印)
  34. aj.captcha.water-mark=我的水印
  35. # 右下角水印字体(不配置时,默认使用文泉驿正黑)
  36. # 由于宋体等涉及到版权,我们jar中内置了开源字体【文泉驿正黑】
  37. # 方式一:直接配置OS层的现有的字体名称,比如:宋体
  38. # 方式二:自定义特定字体,请将字体放到工程resources下fonts文件夹,支持ttf\ttc\otf字体
  39. # aj.captcha.water-font=WenQuanZhengHei.ttf
  40. # 点选文字验证码的文字字体(文泉驿正黑)
  41. # aj.captcha.font-type=WenQuanZhengHei.ttf
  42. # 校验滑动拼图允许误差偏移量(默认5像素)
  43. aj.captcha.slip-offset=5
  44. # aes加密坐标开启或者禁用(true|false)
  45. aj.captcha.aes-status=true
  46. # 滑动干扰项(0/1/2)
  47. aj.captcha.interference-options=2
  48. #点选字体样式 默认Font.BOLD
  49. aj.captcha.font-style=1
  50. #点选字体字体大小
  51. aj.captcha.font-size=25
  52. #点选文字个数,存在问题,暂不支持修改
  53. #aj.captcha.click-word-count=4
  54. aj.captcha.history-data-clear-enable=false
  55. # 接口请求次数一分钟限制是否开启 true|false
  56. aj.captcha.req-frequency-limit-enable=false
  57. # 验证失败5次,get接口锁定
  58. aj.captcha.req-get-lock-limit=5
  59. # 验证失败后,锁定时间间隔,s
  60. aj.captcha.req-get-lock-seconds=360
  61. # get接口一分钟内请求数限制
  62. aj.captcha.req-get-minute-limit=30
  63. # check接口一分钟内请求数限制
  64. aj.captcha.req-check-minute-limit=30
  65. # verify接口一分钟内请求数限制(暂用不上,可后台直接调用captchaService)
  66. #aj.captcha.req-verify-minute-limit=30

CaptchaConfig.java

  1. package com.et.captcha.config;
  2. import com.et.captcha.service.CaptchaCacheServiceRedisImpl;
  3. import com.anji.captcha.properties.AjCaptchaProperties;
  4. import com.anji.captcha.service.CaptchaCacheService;
  5. import com.anji.captcha.service.impl.CaptchaServiceFactory;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.context.annotation.Configuration;
  9. import org.springframework.context.annotation.Primary;
  10. import org.springframework.data.redis.core.StringRedisTemplate;
  11. @Configuration
  12. public class CaptchaConfig {
  13. @Autowired
  14. StringRedisTemplate redisTemplate;
  15. @Bean(name = "CaptchaCacheService")
  16. @Primary
  17. public CaptchaCacheService captchaCacheService(AjCaptchaProperties config){
  18. //缓存类型redis/local/....
  19. CaptchaCacheService ret = CaptchaServiceFactory.getCache(config.getCacheType().name());
  20. if(ret instanceof CaptchaCacheServiceRedisImpl){
  21. ((CaptchaCacheServiceRedisImpl)ret).setStringRedisTemplate(redisTemplate);
  22. }
  23. return ret;
  24. }
  25. }

CaptchaCacheService有很多种实现类,可以动态扩展,具体方式可以参考官方教程,下面提出默认local的实现方式DefaultCaptchaServiceImpl

  1. package com.anji.captcha.service.impl;
  2. import com.anji.captcha.model.common.RepCodeEnum;
  3. import com.anji.captcha.model.common.ResponseModel;
  4. import com.anji.captcha.model.vo.CaptchaVO;
  5. import com.anji.captcha.service.CaptchaService;
  6. import com.anji.captcha.util.StringUtils;
  7. import java.util.Iterator;
  8. import java.util.Properties;
  9. public class DefaultCaptchaServiceImpl extends AbstractCaptchaService {
  10. public DefaultCaptchaServiceImpl() {
  11. }
  12. public String captchaType() {
  13. return "default";
  14. }
  15. public void init(Properties config) {
  16. Iterator var2 = CaptchaServiceFactory.instances.keySet().iterator();
  17. while(var2.hasNext()) {
  18. String s = (String)var2.next();
  19. if (!this.captchaType().equals(s)) {
  20. this.getService(s).init(config);
  21. }
  22. }
  23. }
  24. public void destroy(Properties config) {
  25. Iterator var2 = CaptchaServiceFactory.instances.keySet().iterator();
  26. while(var2.hasNext()) {
  27. String s = (String)var2.next();
  28. if (!this.captchaType().equals(s)) {
  29. this.getService(s).destroy(config);
  30. }
  31. }
  32. }
  33. private CaptchaService getService(String captchaType) {
  34. return (CaptchaService)CaptchaServiceFactory.instances.get(captchaType);
  35. }
  36. public ResponseModel get(CaptchaVO captchaVO) {
  37. if (captchaVO == null) {
  38. return RepCodeEnum.NULL_ERROR.parseError(new Object[]{"captchaVO"});
  39. } else {
  40. return StringUtils.isEmpty(captchaVO.getCaptchaType()) ? RepCodeEnum.NULL_ERROR.parseError(new Object[]{"类型"}) : this.getService(captchaVO.getCaptchaType()).get(captchaVO);
  41. }
  42. }
  43. public ResponseModel check(CaptchaVO captchaVO) {
  44. if (captchaVO == null) {
  45. return RepCodeEnum.NULL_ERROR.parseError(new Object[]{"captchaVO"});
  46. } else if (StringUtils.isEmpty(captchaVO.getCaptchaType())) {
  47. return RepCodeEnum.NULL_ERROR.parseError(new Object[]{"类型"});
  48. } else {
  49. return StringUtils.isEmpty(captchaVO.getToken()) ? RepCodeEnum.NULL_ERROR.parseError(new Object[]{"token"}) : this.getService(captchaVO.getCaptchaType()).check(captchaVO);
  50. }
  51. }
  52. public ResponseModel verification(CaptchaVO captchaVO) {
  53. if (captchaVO == null) {
  54. return RepCodeEnum.NULL_ERROR.parseError(new Object[]{"captchaVO"});
  55. } else if (StringUtils.isEmpty(captchaVO.getCaptchaVerification())) {
  56. return RepCodeEnum.NULL_ERROR.parseError(new Object[]{"二次校验参数"});
  57. } else {
  58. try {
  59. String codeKey = String.format(REDIS_SECOND_CAPTCHA_KEY, captchaVO.getCaptchaVerification());
  60. if (!CaptchaServiceFactory.getCache(cacheType).exists(codeKey)) {
  61. return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_INVALID);
  62. }
  63. CaptchaServiceFactory.getCache(cacheType).delete(codeKey);
  64. } catch (Exception var3) {
  65. this.logger.error("验证码坐标解析失败", var3);
  66. return ResponseModel.errorMsg(var3.getMessage());
  67. }
  68. return ResponseModel.success();
  69. }
  70. }
  71. }

获取验证码

  1. package com.anji.captcha.controller;
  2. import com.anji.captcha.model.common.ResponseModel;
  3. import com.anji.captcha.model.vo.CaptchaVO;
  4. import com.anji.captcha.service.CaptchaService;
  5. import com.anji.captcha.util.StringUtils;
  6. import javax.servlet.http.HttpServletRequest;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.web.bind.annotation.PostMapping;
  9. import org.springframework.web.bind.annotation.RequestBody;
  10. import org.springframework.web.bind.annotation.RequestMapping;
  11. import org.springframework.web.bind.annotation.RestController;
  12. @RestController
  13. @RequestMapping({"/captcha"})
  14. public class CaptchaController {
  15. @Autowired
  16. private CaptchaService captchaService;
  17. public CaptchaController() {
  18. }
  19. @PostMapping({"/get"})
  20. public ResponseModel get(@RequestBody CaptchaVO data, HttpServletRequest request) {
  21. assert request.getRemoteHost() != null;
  22. data.setBrowserInfo(getRemoteId(request));
  23. return this.captchaService.get(data);
  24. }
  25. @PostMapping({"/check"})
  26. public ResponseModel check(@RequestBody CaptchaVO data, HttpServletRequest request) {
  27. data.setBrowserInfo(getRemoteId(request));
  28. return this.captchaService.check(data);
  29. }
  30. public ResponseModel verify(@RequestBody CaptchaVO data, HttpServletRequest request) {
  31. return this.captchaService.verification(data);
  32. }
  33. public static final String getRemoteId(HttpServletRequest request) {
  34. String xfwd = request.getHeader("X-Forwarded-For");
  35. String ip = getRemoteIpFromXfwd(xfwd);
  36. String ua = request.getHeader("user-agent");
  37. return StringUtils.isNotBlank(ip) ? ip + ua : request.getRemoteAddr() + ua;
  38. }
  39. private static String getRemoteIpFromXfwd(String xfwd) {
  40. if (StringUtils.isNotBlank(xfwd)) {
  41. String[] ipList = xfwd.split(",");
  42. return StringUtils.trim(ipList[0]);
  43. } else {
  44. return null;
  45. }
  46. }
  47. }

验证验证码

  1. package com.et.captcha.controller;
  2. import com.anji.captcha.model.common.ResponseModel;
  3. import com.anji.captcha.model.vo.CaptchaVO;
  4. import com.anji.captcha.service.CaptchaService;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.web.bind.annotation.PostMapping;
  7. import org.springframework.web.bind.annotation.RequestMapping;
  8. import org.springframework.web.bind.annotation.RequestParam;
  9. import org.springframework.web.bind.annotation.RestController;
  10. /**
  11. * 后端二次校验接口示例
  12. */
  13. @RestController
  14. @RequestMapping("/auth")
  15. public class LoginController {
  16. @Autowired
  17. private CaptchaService captchaService;
  18. @PostMapping("/login")
  19. public ResponseModel get(@RequestParam("captchaVerification") String captchaVerification) {
  20. CaptchaVO captchaVO = new CaptchaVO();
  21. captchaVO.setCaptchaVerification(captchaVerification);
  22. ResponseModel response = captchaService.verification(captchaVO);
  23. if(response.isSuccess() == false){
  24. //验证码校验失败,返回信息告诉前端
  25. //repCode 0000 无异常,代表成功
  26. //repCode 9999 服务器内部异常
  27. //repCode 0011 参数不能为空
  28. //repCode 6110 验证码已失效,请重新获取
  29. //repCode 6111 验证失败
  30. //repCode 6112 获取验证码失败,请联系管理员
  31. }
  32. return response;
  33. }
  34. }

前端工程代码太多就不贴出来了,具体可以查看web-ui文件家里面的内容,以上只是一些关键代码,所有代码请参见下面代码仓库

代码仓库

  • https://github.com/Harries/springboot-demo

3.测试

第一步:启动后端,启动service/springboot的StartApplication。

第二步:启动前端,终端进入文件夹view/vue,

  1. yarn install
  2. yarn run dev

浏览器登录 http://localhost:8081/#/

e03c50fcfa74f85df7b0347ef73b4358.png

4.引用

  • https://gitee.com/anji-plus/captcha

  • http://www.liuhaihua.cn/archives/710384.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/387162
推荐阅读
相关标签
  

闽ICP备14008679号