前言

验证码作为Web应用的第一道安全防线,其重要性不言而喻。但你是否还在为以下问题烦恼:

  • 传统字符验证码用户体验差,识别率低?
  • 验证码安全性不足,轻易被爬虫破解?
  • 前后端对接繁琐,集成效率低?

今天给大家推荐一款国产开源神级验证码框架——anji-plus-captcha,它不仅支持滑动拼图、点选文字两种主流验证方式,还提供了Spring Boot原生集成方案,5分钟就能搞定验证码功能!本文将从环境搭建到实战部署,手把手教你实现企业级行为验证码,文末附完整源码。

一、为什么选择anji-plus-captcha?

在介绍实战前,先聊聊这款框架的核心优势,看完你就知道为什么它能成为开源验证码领域的佼佼者:

  1. 双模式支持:同时提供滑动拼图和点选文字两种验证方式,可根据业务场景灵活切换
  2. 开箱即用:提供Spring Boot Starter,零配置快速集成,无需编写冗余代码
  3. 分布式友好:原生支持Redis缓存,轻松应对集群部署,解决session共享问题
  4. 高安全性:基于行为轨迹分析,有效抵御自动化工具攻击,验证码过期自动清理
  5. 高度可定制:支持自定义字体、背景图、验证逻辑,满足个性化需求
  6. 完善文档:提供详尽的官方文档和示例代码,降低学习成本

官网地址:https://ajcaptcha.beliefteam.cn/captcha-doc/captchaDoc/html.html
开源仓库:https://gitee.com/belief-team/captcha(星标1.2k+)

二、环境准备与依赖引入

2.1 开发环境

  • JDK 1.8+
  • Spring Boot 2.3.x ~ 2.7.x(亲测兼容)
  • Maven 3.6+
  • Redis 6.0+(可选,分布式部署需用到)

2.2 引入依赖

pom.xml中添加核心依赖,Spring Boot项目无需额外配置:

<!-- anji-plus-captcha 核心依赖 -->
<dependency><groupId>com.anji-plus</groupId><artifactId>captcha-spring-boot-starter</artifactId><version>1.4.0</version> <!-- 最新稳定版 -->
</dependency><!-- Spring Boot Web -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><!-- Redis依赖(分布式部署必选) -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

三、后端实战:5分钟搭建验证码服务

3.1 核心配置(application.yml)

server:port: 8080servlet:context-path: /demo# 验证码核心配置
captcha:# 缓存类型:memory(内存)、redis(分布式)cache-type: redis# 验证码类型:blockPuzzle(滑动拼图)、clickWord(点选文字)mode: clickWord# 点选文字数量(仅clickWord模式有效)click-word-count: 3# 容错率(0-1之间,值越大容错性越强)accuracy: 0.8# 图片宽度(px)width: 350# 图片高度(px)height: 200# 验证码过期时间(秒)expire-second: 120# Redis配置(cache-type=redis时必填)
spring:redis:host: localhostport: 6379password: 123456  # 替换为你的Redis密码database: 0timeout: 2000ms

3.2 后端接口实现(官方标准接口)

根据官网文档,anji-plus-captcha定义了3个核心接口,我们只需编写控制器暴露这些接口即可:

package com.example.captcha.controller;import com.anji.captcha.model.common.ResponseModel;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** 验证码控制器(遵循官方接口规范)*/
@RestController
@RequestMapping("/captcha")
public class CaptchaController {@Autowiredprivate CaptchaService captchaService;/*** 1. 获取验证码(官方标准接口)* 请求URL:/captcha/get* 请求方式:POST*/@PostMapping("/get")public ResponseModel getCaptcha(@RequestBody CaptchaVO captchaVO) {return captchaService.getCaptcha(captchaVO);}/*** 2. 校验验证码(官方标准接口)* 请求URL:/captcha/check* 请求方式:POST*/@PostMapping("/check")public ResponseModel checkCaptcha(@RequestBody CaptchaVO captchaVO) {return captchaService.check(captchaVO);}/*** 3. 二次验证(可选,用于业务接口最终校验)* 请求URL:/captcha/verify* 请求方式:POST*/@PostMapping("/verify")public ResponseModel verifyCaptcha(@RequestBody CaptchaVO captchaVO) {return captchaService.verification(captchaVO);}
}

关键说明

  • 接口路径严格遵循官网规范:/captcha/get/captcha/check/captcha/verify
  • 无需编写Service层代码,框架已通过CaptchaService提供了所有核心实现
  • ResponseModel为框架统一响应对象,包含success(是否成功)、msg(提示信息)、data(业务数据)

四、前端实战:jQuery集成指南(附完整代码)

前端集成是很多开发者容易踩坑的地方,按照官网规范,需使用框架提供的专用JS库,而非普通AJAX请求。

4.1 引入前端资源

<!-- 基础依赖 -->
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script><!-- 验证码核心资源(必须按此顺序引入) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@anji-plus/captcha@1.4.0/dist/css/verify.css">
<script src="https://cdn.jsdelivr.net/npm/@anji-plus/captcha@1.4.0/dist/js/crypto-js.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@anji-plus/captcha@1.4.0/dist/js/aes.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@anji-plus/captcha@1.4.0/dist/js/verify.js"></script>

4.2 点选文字验证码实现(弹出模式)

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>点选文字验证码示例</title><!-- 引入资源(同上) -->
</head>
<body><h3>点选文字验证码(弹出模式)</h3><!-- 验证码容器 --><div id="pointCaptchaContainer"></div><!-- 触发按钮(弹出模式必备) --><button id="pointVerifyBtn" style="padding: 10px 20px; margin-top: 20px;">点击验证</button><script>// 初始化点选验证码(弹出模式)$('#pointCaptchaContainer').pointsVerify({// 后端接口基础地址(必须与后端context-path一致)baseUrl: '/demo/captcha',// 显示模式:pop(弹出式)、fixed(固定式)mode: 'pop',// 弹出模式触发按钮ID(必须与按钮id一致)containerId: 'pointVerifyBtn',// 图片尺寸imgSize: {width: '350px',height: '200px'},// 验证成功回调success: function(params) {console.log('验证成功,返回参数:', params);alert('验证成功!二次验证参数:' + params.captchaVerification);// 此处可调用业务接口,将params.captchaVerification传递给后端进行二次校验// $.post('/demo/login', {//     username: 'test',//     password: '123',//     captchaVerification: params.captchaVerification// }, function(res) { ... });},// 验证失败回调error: function() {alert('验证失败,请重试!');},// 验证码加载完成回调ready: function() {console.log('点选验证码初始化完成');}});</script>
</body>
</html>

4.3 滑动拼图验证码实现(固定模式)

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>滑动拼图验证码示例</title><!-- 引入资源(同上) -->
</head>
<body><h3>滑动拼图验证码(固定模式)</h3><!-- 验证码容器(固定模式直接显示在此处) --><div id="slideCaptchaContainer" style="margin-top: 20px;"></div><script>// 初始化滑动验证码(固定模式)$('#slideCaptchaContainer').slideVerify({baseUrl: '/demo/captcha',mode: 'fixed',// 滑动条提示文字explain: '向右滑动完成验证',// 图片尺寸imgSize: {width: '350px',height: '200px'},// 滑动条尺寸barSize: {width: '350px',height: '40px'},// 验证成功回调success: function(params) {console.log('滑动验证成功,返回参数:', params);alert('滑动验证成功!');},// 验证失败回调error: function() {alert('滑动失败,请重试!');}});</script>
</body>
</html>

前端核心配置说明

  • baseUrl必须包含后端context-path(如示例中的/demo),否则会出现404错误
  • modepop时,containerId必须与触发按钮的id一致
  • success回调中的params.captchaVerification是二次验证的关键参数,需传递给业务接口

五、高级特性:自定义验证码资源

5.1 自定义字体库

  1. src/main/resources目录下创建font文件夹,放入字体文件(如simhei.ttf
  2. application.yml中配置字体路径:
captcha:font-path:- classpath:font/simhei.ttf  # 支持多个字体文件,随机使用

5.2 自定义背景图

  1. src/main/resources目录下创建captcha/background文件夹,放入背景图片(jpg/png格式)
  2. 配置自定义背景图:
captcha:# 启用自定义背景图use-custom-background: true# 背景图目录background-image-dir: classpath:captcha/background

六、避坑指南:新手常遇问题解决方案

  1. 后端接口404错误

    • 检查baseUrl是否包含context-path(如/demo/captcha而非/captcha
    • 确认接口路径是否为/captcha/get/captcha/check(严格区分大小写)
  2. 验证码图片加载失败

    • 检查Redis是否启动,配置是否正确(cache-type=redis时必须)
    • 查看后端日志,是否有字体文件加载失败的错误(需确保字体文件存在)
  3. 前端报“containerId不存在”

    • mode=pop时,containerId必须与触发按钮的id完全一致
    • 确保初始化代码在DOM加载完成后执行(可放入$(document).ready()中)
  4. 验证成功但业务接口提示“验证码已失效”

    • 检查expire-second配置,避免过期时间过短
    • 确保success回调中及时调用业务接口(验证码过期前)

七、效果演示与源码获取

7.1 点选验证码效果

在这里插入图片描述

7.2 滑动验证码效果

在这里插入图片描述

7.3 完整源码获取

关注公众号【豌豆哥哥】,回复“验证码”即可获取完整项目源码,包含前后端所有代码和配置文件。

总结

本文详细介绍了如何基于anji-plus-captcha实现企业级行为验证码,从环境搭建到高级定制,涵盖了开发过程中的各个关键环节。这款框架凭借其易用性和强大的功能,非常适合中小型项目快速集成验证码功能。

相比传统验证码,行为验证码在安全性和用户体验上都有明显优势,而anji-plus-captcha则是Java生态中为数不多的优秀开源方案。希望本文能帮助你快速掌握验证码开发技巧,让你的项目安全又好用!

如果觉得本文对你有帮助,别忘了点赞+收藏+关注,后续会分享更多Java实战教程!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/88581.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/88581.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/88581.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML-八股

1、DOM和BOM DOM是表示HTML或者XML文档的标准的对象模型&#xff0c;将文档中每个组件&#xff08;元素、属性等&#xff09;都作为一个对象&#xff0c;使用JS来操作这个对象&#xff0c;从而动态改变页面内容&#xff0c;结合等。 DOM是以树型结构组织文档内容&#xff0c;树…

ADI的EV-21569-SOM核心板和主板转接卡的链接说明

ADI提供给客户很多DSP的核心板&#xff0c;比如EV-21569-SOM&#xff0c;EV-21593-SOM&#xff0c;EV-SC594-SOM等&#xff0c;非常多&#xff0c;但是没有底板&#xff0c;光一个核心板怎么用呢&#xff1f;于是我就在想&#xff0c;我的21569评估板就有通用底板&#xff0c;能…

基于 Redisson 实现分布式系统下的接口限流

在高并发场景下&#xff0c;接口限流是保障系统稳定性的重要手段。常见的限流算法有漏桶算法、令牌桶算法等&#xff0c;而单机模式的限流方案在分布式集群环境下往往失效。本文将介绍如何利用 Redisson 结合 Redis 实现分布式环境下的接口限流&#xff0c;确保集群中所有节点的…

ubuntu播放rosbag包(可鼠标交互)

1 前言 众所周知&#xff0c;ubuntu中播放bag包最主要的工具是rviz&#xff0c;然而rviz有一个无法忍受的缺陷就是不支持鼠标回滚&#xff0c;并且显示的时间的ros时间&#xff0c;不是世界时间&#xff0c;因此在遇到相关bug时不能与对应的世界时间对应。基于以上&#xff0c…

一文理解缓存的本质:分层架构、原理对比与实战精粹

&#x1f4d6; 推荐阅读&#xff1a;《Yocto项目实战教程:高效定制嵌入式Linux系统》 &#x1f3a5; 更多学习视频请关注 B 站&#xff1a;嵌入式Jerry 一文理解缓存的本质&#xff1a;分层架构、原理对比与实战精粹 “缓存让系统飞起来”——但每一层缓存有何不同&#xff1f;…

【离线数仓项目】——电商域DIM层开发实战

摘要本文主要介绍了电商域离线数仓项目中DIM层的开发实战。首先阐述了DIM层的简介、作用、设计特征、典型维度分类以及交易支付场景下的表示例和客户维度表设计。接着介绍了DIM层设计规范&#xff0c;包括表结构设计规范、数据处理规范以及常见要求规范。然后详细讲解了DIM层的…

Unreal Engine 自动设置图像

void UYtGameSettingSubsystem::RunHardwareBenchmark(int32 WorkScale, float CPUMultiplier, float GPUMultiplier) {UGameUserSettings* UserSettings UGameUserSettings::GetGameUserSettings();if (UserSettings){// 运行基准测试&#xff08;异步操作&#xff0c;可能需…

使用Spring Boot和PageHelper实现数据分页

在Spring Boot项目中&#xff0c;利用PageHelper插件可以轻松实现数据分页功能。以下是具体的实现步骤和代码示例。添加依赖在项目的pom.xml文件中添加PageHelper和MyBatis的依赖。<dependency><groupId>com.github.pagehelper</groupId><artifactId>p…

【IT-Infra】从ITIL到CMDB,配置管理,资产管理,物理机与设备管理(含Infra系列说明)

【IT-Infra】从ITIL到CMDB&#xff0c;配置管理&#xff0c;资产管理&#xff0c;物理机与设备管理&#xff08;含Infra系列说明&#xff09; 文章目录序&#xff1a;Infra系列说明1、ITIL 信息技术基础架构库&#xff08;起源&#xff09;2、CMDB 配置管理数据库&#xff08;I…

vue使用printJS实现批量打印及单个打印 避免空白页

本文介绍了使用print-js库实现批量打印功能的实现方法。通过安装print-js依赖后,创建一个batchPrintAction方法,该方法接收选中行数据,生成包含多个标签页的HTML字符串。每个标签页以表格形式展示6个数据字段,并设置了80mm50mm的标签尺寸。方法使用PrintJS进行打印,配置了…

C++ 选择排序、冒泡排序、插入排序

选择排序&#xff1a;是一种简单直观的排序算法&#xff0c;每次均是选择最小&#xff08;大&#xff09;的元素进行排序。选择排序算法思想&#xff1a;1 在未排序序列中找到最小&#xff08;大&#xff09;元素&#xff0c;存放到排序序列的起始位置2 再从剩余未排序元素中继…

Linux入门篇学习——Linux 编写第一个自己的命令,make 工具和 makefile 文件

目录 一、Linux 编写第一个自己的命令 1.命令的概念 2.定义一个自己的命令 二、make 工具和 makefile 文件 1.使用 make 工具 2.makefile文件 一、Linux 编写第一个自己的命令 1.命令的概念 命令就是可执行程序。 比如说我们输入 ls -al &#xff0c;ls 就是可执行程序的…

实验一 接苹果

主要步骤苹果树制作&#xff08;苹果与篮子的制作同理&#xff09;为苹果添加标签相机位置设置与游戏面板长宽比设置&#xff08;16:9&#xff09;苹果下落设置&#xff08;将苹果从平抛运动改为垂直下落&#xff09;通过设置物理图层并更改碰撞矩阵表实现通过PlayerPrefs实现游…

Nginx服务器集群:横向扩展与集群解决方案

横向扩展&#xff1a;基础概念 在深入了解Nginx的横向扩展细节之前&#xff0c;首先理解横向扩展的含义及其重要性。横向扩展是指通过增加服务器数量来分散负载并提升整体性能。这与纵向扩展形成对比&#xff0c;纵向扩展是指在单个服务器上增加更多资源&#xff08;如CPU、内…

缺陷的生命周期(Bug Life Cycle)是什么?

一、缺陷生命周期的定义缺陷生命周期是指一个Bug从被发现到最终关闭的完整流程&#xff0c;反映了缺陷在不同角色&#xff08;测试、开发、产品等&#xff09;间的流转状态。它是软件测试流程的核心管理模型&#xff0c;直接影响团队协作效率。二、标准缺陷生命周期阶段以下是通…

AtCoder Beginner Contest 333(A,B,C,D,E,F)

AtCoder Beginner Contest 333 A 题意 输出n个n(n<9) 代码 #include<bits/stdc.h> using namespace std; void solve(){int n;cin>>n;for(int i1;i<n;i)cout<<n; } signed main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int T__1;//cin…

留学真相:凌晨两点被海关拦下时,我才明白人生没有退路

> 独立不是选择&#xff0c;而是生存的必修课下飞机那一刻&#xff0c;幻想中的“镀金生活”瞬间崩塌。伦敦海关凌晨两点的灯光下&#xff0c;你颤抖着翻找学校文件&#xff0c;手机信号格空空如也&#xff1b;大巴误点后&#xff0c;你拖着两个32公斤的行李箱站在阴雨中&am…

探索AIGC领域DALL·E 2的图像生成与人类创意的融合

探索AIGC领域DALLE 2的图像生成与人类创意的融合关键词&#xff1a;AIGC、DALLE 2、图像生成、人类创意、创意融合摘要&#xff1a;本文聚焦于AIGC领域中DALLE 2的图像生成技术与人类创意的融合。首先介绍了相关背景&#xff0c;包括DALLE 2的发展历程和人类创意在艺术创作中的…

【ECharts】多个ECharts版本共存解决方案

多个ECharts版本共存解决方案 在单个HTML页面中使用多个ECharts版本的关键在于避免全局命名空间冲突。下面我将展示一个完整的解决方案&#xff0c;包含两种不同的实现方法。 解决方案思路命名空间隔离法&#xff1a; 使用不同的全局变量名保存不同版本的ECharts在加载新版本前…

力扣热门算法题 204.计数质数,207.课程表,213.打家劫舍II

力扣热门算法题 204.计数质数&#xff0c;207.课程表&#xff0c;213.打家劫舍II&#xff0c;每题做详细思路梳理&#xff0c;配套Python&Java双语代码&#xff0c; 2025.07.07 可通过leetcode所有测试用例。 目录 204.计数质数 解题思路 完整代码 207.课程表 解题思…