本文目录导读:

在Java中验证验证码有效性,通常有两种场景:前后端分离(后端生成+校验)和传统单体应用(Session存储),下面给出3种主流验证码库的实现案例。
基础逻辑:验证码验证的本质
无论用哪种库,核心步骤都是:
- 生成阶段:生成验证码文本 → 存入服务端(Session/Redis) → 返回图片给前端
- 验证阶段:用户提交文本 → 从服务端取出正确文本 → 比对(通常忽略大小写)→ 清除/标记已使用
案例一:使用 Kaptcha(传统 Session 方案)
适用于:单体应用、不涉及分布式 Session 的项目。
1 依赖(Maven)
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
2 生成验证码 Controller
@GetMapping("/captcha")
public void getCaptcha(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 1. 设置响应类型
response.setDateHeader("Expires", 0);
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
response.addHeader("Cache-Control", "post-check=0, pre-check=0");
response.setHeader("Pragma", "no-cache");
response.setContentType("image/jpeg");
// 2. 生成验证码文本(Kaptcha默认使用DefaultKaptcha)
String capText = captchaProducer.createText();
// 3. 存入 Session(key 自定义,如 "captchaCode")
request.getSession().setAttribute("captchaCode", capText);
// 4. 生成图片并写入响应流
BufferedImage bi = captchaProducer.createImage(capText);
ServletOutputStream out = response.getOutputStream();
ImageIO.write(bi, "jpg", out);
out.flush();
out.close();
}
3 验证验证码有效性 Controller
@PostMapping("/login")
public String login(@RequestParam String username,
@RequestParam String password,
@RequestParam String captchaInput,
HttpServletRequest request) {
// 1. 从 Session 获取正确验证码
String correct = (String) request.getSession().getAttribute("captchaCode");
// 2. 清除验证码(防止重复使用)
request.getSession().removeAttribute("captchaCode");
// 3. 有效性校验
if (correct == null || !correct.equalsIgnoreCase(captchaInput)) { // 忽略大小写
return "验证码错误或已过期";
}
// 4. 验证通过,继续业务逻辑
return "登录成功";
}
案例二:使用 EasyCaptcha(支持 Redis + 分布式)
适用于:前后端分离、分布式部署。
1 依赖
<dependency>
<groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId>
<version>1.6.2</version>
</dependency>
2 生成验证码(UUID + Redis 存储)
@GetMapping("/captcha")
public Result<Map<String, String>> getCaptcha() {
// 1. 生成验证码对象(数字+字母,4位)
SpecCaptcha captcha = new SpecCaptcha(130, 48, 4);
// 2. 获取文本(如 "A3bC")
String code = captcha.text().toLowerCase(); // 统一转小写存储
// 3. 生成唯一标识符(作为Redis的key)
String uuid = UUID.randomUUID().toString().replace("-", "");
// 4. 存入 Redis(过期时间 5 分钟)
redisTemplate.opsForValue().set(RedisKeys.CAPTCHA_KEY + uuid, code, 5, TimeUnit.MINUTES);
// 5. 返回给前端:uuid(作为凭证) + 图片base64
Map<String, String> map = new HashMap<>();
map.put("captchaKey", uuid);
map.put("captchaImg", captcha.toBase64()); // 前端直接<img src="data:image/...">显示
return Result.success(map);
}
3 验证验证码有效性 Controller
@PostMapping("/login")
public Result<?> login(@RequestBody LoginForm form) {
// 1. 从请求中拿到 captchaKey 和前端输入的 captchaInput
String captchaKey = form.getCaptchaKey();
String captchaInput = form.getCaptchaInput();
// 2. 从 Redis 取出正确的验证码
String correctCode = redisTemplate.opsForValue().get(RedisKeys.CAPTCHA_KEY + captchaKey);
// 3. **立即删除**(防止多次使用)
redisTemplate.delete(RedisKeys.CAPTCHA_KEY + captchaKey);
// 4. 有效性校验
if (correctCode == null) {
return Result.error("验证码已过期,请重新获取");
}
if (!correctCode.equalsIgnoreCase(captchaInput)) {
return Result.error("验证码错误");
}
// 5. 验证通过,继续业务
return Result.success("登录成功");
}
关键验证规则(必须注意)
1 大小写不敏感
推荐统一转为小写后再比较:
correctCode.equalsIgnoreCase(inputCode); // 或者 correctCode.toLowerCase().equals(inputCode.toLowerCase());
2 一次性使用
- 无论是 Session 还是 Redis,验证成功后必须立即删除。
- 防止同一个验证码被重复提交。
3 过期机制
- Session:默认 30 分钟失效,建议手动设置更短(如 5 分钟)。
- Redis:设置过期时间
5, TimeUnit.MINUTES。
4 防暴力破解
- 同一 IP 短时间内验证失败次数过多 → 临时锁定(可加计数器到 Redis)。
- 验证码本身可以加 干扰线、扭曲、噪点(EasyCaptcha / Kaptcha 配置)。
完整校验流程图
前端 后端 Redis / Session
───────── ────────── ────────────
请求获取验证码 ──→ 生成code + 存储Code ──→ 保存code
↓
返回{img, key} ←── code不返回给前端
↓
用户填写验证码 + key
↓
提交表单 ──→ 取出code(根据key)
↓
比较code ←── 忽略大小写比对比
↓
删除key对应的code ──→ 清除
↓
返回成功/失败
| 场景 | 推荐技术 | 存储方案 | 验证核心 |
|---|---|---|---|
| 单体应用 | Kaptcha | Session | session.getAttribute |
| 分布式 / 前后端分离 | EasyCaptcha + Redis | Redis + UUID | redis.get(key) + 删除 |
| 高安全需求 | 算术验证码 / 滑动验证 | 均可 | 同上 + 轨迹校验 |
验证码有效验证的黄金三原则:
- 存储 ≠ 返回(code不进返回体)
- 验证即删(一次有效)
- 忽略大小写
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播