文章适合谁?解决什么问题?

这篇文章适合 正在使用 SpringBoot 开发 Web 系统的初学者或课程设计、毕业设计阶段的同学
我在给学生项目做功能检查时,经常遇到这样的问题:

验证码功能要么依赖过重,要么逻辑说不清楚,老师一问就答不上来。

因此本文记录的是一种 基于 SpringBoot + Hutool + 原生 JavaScript 的验证码实现方式,
目标不是“功能炫”,而是 逻辑清楚、代码可讲、实现可复现


一、实现目标与技术选型说明

本文实现的是一个最基础、但完整的浏览器验证码功能,具体包括:

  • 后端生成图片验证码
  • 浏览器端展示验证码图片
  • 支持点击图片刷新验证码
  • 后端完成验证码校验逻辑

对应的技术选型如下:

  • 后端框架:SpringBoot
  • 验证码工具:Hutool Captcha
  • 前端技术:HTML + 原生 JavaScript
  • 验证码存储方式:HttpSession

说明:本文刻意 不使用前端框架、不引入 Redis,是为了让逻辑更容易被初学者理解。


二、后端验证码生成(SpringBoot + Hutool)

1. 引入 Hutool 依赖

pom.xml 中添加依赖:

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.25</version>
</dependency>

Hutool 提供了现成的验证码工具类,可以直接生成图片并获取验证码内容,避免手写图形逻辑。


2. 编写验证码接口

@RestController
public class CaptchaController {

    @GetMapping("/captcha")
    public void captcha(HttpServletRequest request,
                        HttpServletResponse response) throws IOException {

        // 创建验证码对象
        LineCaptcha captcha = CaptchaUtil.createLineCaptcha(120, 40, 4, 10);

        // 将验证码内容存入 Session
        request.getSession().setAttribute("captcha_code", captcha.getCode());

        // 设置响应类型
        response.setContentType("image/png");

        // 输出验证码图片
        captcha.write(response.getOutputStream());
    }
}

关键细节说明

  • 120 × 40 是比较通用的验证码尺寸
  • 验证码字符数为 4,便于用户输入
  • 使用 Session 保存验证码,便于后续校验
  • 接口直接返回图片流,前端无需额外处理

三、前端验证码展示与刷新(原生 JavaScript)

1. HTML 页面结构

<img id="captchaImg"
     src="/captcha"
     alt="验证码"
     title="点击刷新验证码">

浏览器加载页面时,会自动请求 /captcha 接口并显示验证码图片。


2. 点击刷新验证码

<script>
    const captchaImg = document.getElementById("captchaImg");

    captchaImg.onclick = function () {
        this.src = "/captcha?time=" + new Date().getTime();
    };
</script>

为什么要加时间戳?

  • 防止浏览器缓存旧图片
  • 确保每次点击都会请求新的验证码
  • 是原生 JavaScript 中最常见、也最稳妥的做法

四、验证码校验逻辑示例

在用户提交表单时,对验证码进行校验:

@PostMapping("/login")
public String login(HttpServletRequest request,
                    @RequestParam("captcha") String captchaInput) {

    String sessionCaptcha =
        (String) request.getSession().getAttribute("captcha_code");

    if (sessionCaptcha == null ||
        !sessionCaptcha.equalsIgnoreCase(captchaInput)) {
        return "验证码错误";
    }

    return "验证码校验通过";
}

校验逻辑说明

  • 使用 equalsIgnoreCase 忽略大小写
  • 校验完成后,实际项目中建议清除 Session 中的验证码
  • 若并发量较大,可考虑使用 Redis 存储

五、方案适用场景与局限性

适合的场景

  • 课程设计、毕业设计
  • 教学示例、功能演示项目
  • 管理后台、小型系统

不适合的场景

  • 高并发业务系统
  • 对安全性要求极高的登录场景
  • 需要滑块、行为验证的复杂系统

六、总结与延伸

回到文章开头提到的问题:
验证码并不难,难的是能不能把实现逻辑讲清楚。

这种基于 SpringBoot、Hutool 和原生 JavaScript 的实现方式,没有走捷径,也没有过度封装,非常适合用于:

  • 课堂答辩时的功能讲解
  • 毕业设计中“系统功能模块说明”章节
  • 开题或中期检查中的技术说明
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐