用 Spring Boot 和 anji-captcha 实现图片生成与前后端交互

在 Web 开发中,动态生成图片并通过 API 传递给前端展示是一个常见需求,例如验证码生成、动态图表等。本文将以 Java 的 Spring Boot 框架和 anji-captcha 依赖为例,详细讲解如何生成验证码图片、如何通过 JSON 传递给前端、前端如何渲染,以及前端判定成功后如何回传结果。同时,我们会解答一个有趣的问题:JSON 不是通常用来传递文本的吗?为什么可以传递图片?图片又是如何通过 Base64 编码实现的?

1. 后端如何生成图片:基于 anji-captcha

anji-captcha 是一个轻量级的验证码生成工具,支持滑块验证码和点击验证码等形式。它内置了图片生成逻辑,我们只需通过配置将其集成到 Spring Boot 项目中。

依赖配置

首先,在 pom.xml 中引入 anji-captcha 依赖:

xml 复制代码
<dependency>
    <groupId>com.anji-plus</groupId>
    <artifactId>captcha-spring-boot-starter</artifactId>
    <version>1.3.2</version>
</dependency>
后端实现

在 Spring Boot 中,我们通过控制器调用 anji-captcha 的服务生成验证码图片。以下是一个简单的实现:

java 复制代码
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.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CaptchaController {

    @Autowired
    private CaptchaService captchaService;

    @GetMapping("/generate-captcha")
    public ResponseModel generateCaptcha() {
        CaptchaVO captchaVO = new CaptchaVO();
        captchaVO.setCaptchaType("blockPuzzle"); // 设置验证码类型为滑块验证码
        ResponseModel response = captchaService.get(captchaVO);
        return response;
    }
}

运行这段代码后,captchaService.get() 会返回一个 ResponseModel,其中包含验证码图片的 Base64 编码字符串。anji-captcha 内部已经将生成的图片(通常是 PNG 格式)转换为 Base64 格式。

返回的 JSON 格式

假设我们请求 /generate-captcha,后端返回的 JSON 可能是这样的:

json 复制代码
{
  "success": true,
  "repCode": "0000",
  "repData": {
    "captchaId": "abc123",
    "originalImageBase64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAABkCAYAAADp90t...",
    "jigsawImageBase64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAABkCAYAAADp90t...",
    "token": "xyz789"
  },
  "repMsg": "操作成功"
}
  • originalImageBase64:背景图片的 Base64 编码。
  • jigsawImageBase64:滑块图片的 Base64 编码。
  • captchaIdtoken:用于后续验证。

2. 如何将图片传递给前端

在上面的 JSON 中,图片数据通过 originalImageBase64jigsawImageBase64 字段传递。这些字段的值是图片的 Base64 编码字符串,前面带有 MIME 类型前缀 data:image/png;base64,,告诉前端这是一个 PNG 格式的图片数据。

这种方法的好处是:

  • JSON 本身是文本格式,Base64 编码将二进制图片数据转为文本,完美兼容 JSON。
  • 前端无需额外请求图片资源,直接从 JSON 中提取并渲染。

3. 前端如何渲染图片

前端拿到 JSON 后,可以直接使用 <img> 标签渲染 Base64 编码的图片。以下是一个简单的 JavaScript 和 HTML 示例:

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>Captcha Demo</title>
</head>
<body>
    <img id="background" alt="Background Image">
    <img id="jigsaw" alt="Jigsaw Image">
    <button onclick="verifyCaptcha()">验证</button>

    <script>
        // 获取验证码图片
        fetch('/generate-captcha')
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    let repData = data.repData;
                    document.getElementById('background').src = repData.originalImageBase64;
                    document.getElementById('jigsaw').src = repData.jigsawImageBase64;
                    window.captchaId = repData.captchaId; // 保存 captchaId 用于验证
                    window.token = repData.token; // 保存 token 用于验证
                }
            });

        // 模拟用户拖动滑块后的验证逻辑
        function verifyCaptcha() {
            let verifyData = {
                captchaId: window.captchaId,
                token: window.token,
                point: { x: 150, y: 50 } // 假设用户拖动到这个位置
            };
            fetch('/verify-captcha', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(verifyData)
            })
            .then(response => response.json())
            .then(result => {
                if (result.success) {
                    alert('验证成功!');
                } else {
                    alert('验证失败!');
                }
            });
        }
    </script>
</body>
</html>
  • 渲染img.src 直接赋值为 Base64 字符串,前端浏览器会自动解码并显示图片。
  • 用户交互 :用户拖动滑块后,前端记录滑块位置(如 {x: 150, y: 50})。

4. 前端判定成功与否后如何回传

用户完成滑块操作后,前端将验证数据回传给后端。回传的 JSON 示例:

json 复制代码
{
  "captchaId": "abc123",
  "token": "xyz789",
  "point": {
    "x": 150,
    "y": 50
  }
}

后端验证逻辑(基于 anji-captcha):

java 复制代码
@PostMapping("/verify-captcha")
public ResponseModel verifyCaptcha(@RequestBody CaptchaVO captchaVO) {
    return captchaService.check(captchaVO);
}

captchaService.check() 会校验用户提交的滑块位置是否正确,并返回结果:

json 复制代码
{
  "success": true,
  "repCode": "0000",
  "repMsg": "验证成功"
}

前端根据 success 字段判断验证是否成功。

5. JSON 为什么能传递图片?Base64 编码是怎么回事?

你可能好奇:JSON 不是用来传递文本的吗?怎么能传递图片呢?

实际上,JSON 本身只支持文本数据,而图片是二进制数据。要解决这个矛盾,我们需要将图片的二进制数据转换为文本形式,这就是 Base64 编码 的作用。

Base64 编码原理

Base64 是一种将二进制数据编码为 ASCII 字符串的方法:

  • 它将每 3 个字节(24 位)的二进制数据分成 4 个 6 位单元。
  • 每个 6 位单元映射到一个由 64 个字符(A-Z、a-z、0-9、+、/)组成的字符表。
  • 编码后的字符串长度会增加约 33%,因为 3 个字节变成 4 个字符。

在 Java 中,anji-captcha 内部使用类似以下代码生成 Base64:

java 复制代码
import java.util.Base64;

byte[] imageBytes = /* 图片的字节数据 */;
String base64String = Base64.getEncoder().encodeToString(imageBytes);
// 前端可识别的格式
String dataUrl = "data:image/png;base64," + base64String;
为什么用 Base64?
  • 兼容性:JSON 要求数据是文本,Base64 将二进制转为文本。
  • 简单性:无需额外请求图片文件,减少 HTTP 请求。
  • 局限性:Base64 字符串比原始二进制数据大,适合小型图片(如验证码),不适合大文件。

总结

通过 Spring Boot 和 anji-captcha,我们实现了一个完整的图片生成与交互流程:

  1. 后端生成验证码图片并转为 Base64 编码,通过 JSON 传递。
  2. 前端直接用 <img> 标签渲染 Base64 图片。
  3. 用户操作后,前端回传验证数据,后端返回结果。

相关推荐
申雪菱5 分钟前
Scheme语言的数据挖掘
开发语言·后端·golang
程序员一诺9 分钟前
【Flask开发】嘿马文学web完整flask项目第1篇:简介【附代码文档】
后端·python·flask·框架
Bruce_Liuxiaowei17 分钟前
基于Flask的MBA考生成绩查询系统设计与实现
后端·python·flask
欧宸雅21 分钟前
HTML语言的空值合并
开发语言·后端·golang
方瑾瑜1 小时前
Visual Basic语言的物联网
开发语言·后端·golang
赖皮猫1 小时前
PIKIE-RAG 本地部署实践
后端·python·flask
Asthenia04121 小时前
面试回顾:Java RMI 问题解析(续)
后端
无名之逆1 小时前
[特殊字符] Hyperlane 框架:高性能、灵活、易用的 Rust 微服务解决方案
运维·服务器·开发语言·数据库·后端·微服务·rust
Asthenia04122 小时前
面试回顾:Java RMI 问题解析
后端
uhakadotcom2 小时前
Python 中的 @staticmethod 和 @classmethod 详解
后端·面试·github