验证码实现

验证码实现

在 Java 开发中,最常用的验证码类型有图片验证码、短信 / 邮箱验证码、行为验证码,在这里我们主要介绍一下图片验证码的相关内容。

easy-captcha

核心定位:

easy-captcha 是一款专为 Java Web 场景设计的轻量级开源验证码库,核心目标是简化各类验证码的开发与集成,替代手写验证码的复杂底层实现。

核心价值:

该库封装了画布创建、随机字符生成、干扰线 / 噪点绘制、IO 流输出等所有手写验证码的底层细节,大幅降低开发成本,开发者仅需几行代码即可快速实现验证码功能,无需关注图形绘制的底层逻辑。

核心特性

零依赖轻量化:仅依赖 JDK 内置的 AWT 绘图类库,无需引入任何第三方依赖,打包体积小,部署无额外成本;

多类型全覆盖:支持静态图片、动态 GIF、算术运算、中文汉字等主流验证码类型,满足绝大多数业务场景需求;

高度可定制化:支持自定义验证码长度、图片尺寸、字体样式、颜色方案、干扰元素等,适配个性化视觉需求;

输出方式灵活:支持三种输出形式 ------ 本地文件、HTTP 响应流(适配传统 Web 项目)、Base64 编码字符串(适配前后端分离项目);

Web 生态友好:原生适配 Servlet/JSP、Spring MVC、Spring Boot 等 Java Web 技术栈,提供开箱即用的工具类,无需额外适配。

引入依赖坐标

xml 复制代码
        <dependency>
            <groupId>com.github.whvcse</groupId>
            <artifactId>easy-captcha</artifactId>
            <version>1.6.2</version>
        </dependency>

1.6.2 是 easy-captcha 的稳定版本,适配 JDK 8+,如果项目使用的是 JDK 11+,建议使用 1.7.0 及以上版本,修复了高版本 JDK 的兼容问题。

支持的验证码类型

静态验证码:静态 PNG 格式,性能最高

子类型 实现类 核心特点 适用场景
轻量字符验证码 CharCaptcha 专注数字 / 字母 / 混合字符 对性能要求高的简单场景
纯数字验证码 NumericCaptcha 仅含 0-9 数字 普通登录、简单验证
纯字母验证码 LetterCaptcha 含大小写英文字母 中等安全需求的验证
数字 + 大写字母验证码 SpecCaptcha 数字 + 大写字母,且剔除易混淆字符 绝大多数通用登录 / 注册场景
算术运算验证码 ArithmeticCaptcha 生成 0-99 加减乘算术题 登录 / 注册等核心业务场景
中文验证码 ChineseCaptcha 随机中文汉字 防破解能力远高于字符类,高安全需求

动态验证码:GIF 格式,防识别最强

子类型 实现类 核心特点 适用场景
字符 GIF 验证码 GifCaptcha 字符随机位移 / 闪烁 高安全防爬虫场景
中文 GIF 验证码 ChineseGifCaptcha 汉字随机位移 / 闪烁 极高安全需求
算术 GIF 验证码 ArithmeticGifCaptcha 算术题字符动态位移 核心业务和高防爬需求

下面具体介绍 SpecCaptcha 类

SpecCaptcha

SpecCaptcha 是开源验证码库 easy-captcha 面向通用 Web 验证场景设计的静态图片验证码实现类。

该类的核心字符集限定为数字(0-9)与大写英文字母(A-Z),并通过剔除 0/O、1/I、8/B 等视觉易混淆字符,降低用户识别误差。输出形态为 PNG 格式静态图片,具备生成效率高、加载速度快的特性,在易用性、安全防护能力与用户体验间实现平衡,是 Java Web 项目中登录、注册等常规验证场景的主流选型。

下面介绍该库的部分使用方法,主要介绍构造方法、核心获取 / 输出方法 以及 样式配置方法。

构造方法

用于创建 SpecCaptcha 实例,支持自定义图片尺寸、验证码长度

方法签名 说明
SpecCaptcha() 无参构造:默认宽度 150、高度 50、验证码长度 4
SpecCaptcha(int width, int height) 指定宽高,验证码长度默认 4
SpecCaptcha(int width, int height, int len) 自定义宽、高、验证码长度(最常用)

获取 / 输出方法

这类方法是验证码使用的核心,用于获取验证码文本、生成图片、输出到流:

方法签名 说明
String text() 获取生成的验证码文本
BufferedImage image() 生成验证码图片的 BufferedImage 对象
void out(OutputStream os) 将验证码图片以 PNG 格式写入输出流(Web 场景中写入响应流)
void out(ServletOutputStream sos) 重载方法,适配 Servlet 响应流(简化 Web 输出)
String toBase64() 将验证码图片转换为 Base64 编码字符串(适用于前后端分离场景)
String toBase64(boolean deletePrefix) 转换为 Base64,deletePrefix=true 则移除 data:image/png;base64, 前缀

样式配置方法

自定义验证码外观,用于调整验证码的字体、尺寸、干扰元素、背景等样式,均为 set/get 成对出现:

void setWidth(int width) / int getWidth() 设置 / 获取验证码图片宽度

void setHeight(int height) / int getHeight() 设置 / 获取验证码图片高度

void setLen(int len) / int getLen() 设置 / 获取验证码字符长度

void setCharType(int charType) / int getCharType() 设置 / 获取字符类型(核心),可选值:

Captcha.TYPE_DEFAULT:中文

Captcha.TYPE_ONLY_NUMBER:纯数字

Captcha.TYPE_ONLY_CHAR:纯字母

Captcha.TYPE_MIX:数字 + 字母

void setFont(Font font) / Font getFont() 设置 / 获取字符字体(支持自定义字体、字号、加粗)

void setInterfereLineCount(int count) / int getInterfereLineCount() 设置 / 获取干扰线数量

void setNoiseCount(int count) / int getNoiseCount() 设置 / 获取干扰像素点

void setBackground(Color color) / Color getBackground() 设置 / 获取图片背景色

void setCharColor(Color color) / Color getCharColor() 设置 / 获取字符颜色(默认随机颜色)

验证码实现的代码示例

前端 vue 代码示例:

html 复制代码
<template>
  <div class="captcha-container">
    <el-form ref="captchaForm" :model="loginForm" :rules="loginRules">
      <el-form-item prop="captcha">
        <el-input
          ref="captcha"
          v-model="loginForm.captcha"
          placeholder="请输入验证码"
          prefix-icon="el-icon-circle-check"
          name="captcha"
          style="width: 65%"
          size="default"
        />
        <!-- 验证码图片:支持点击刷新与展示图片 -->
        <el-image
          class="captcha-img"
          :src="captchaPath"
          @click="getCaptcha()"
        />
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
// 验证码API导入
import { getCaptchaImg } from '@/api/sys/login'

export default {
  name: 'CaptchaDemo',
  data() {
    return {
      captchaPath: '',
      loginForm: {
        captcha: '', // 用户输入的验证码
        uuid: ''     // 验证码唯一标识(传给后端验证用)
      },
      // 验证码输入校验规则
      loginRules: {
        captcha: [{ required: true, message: '请输入验证码', trigger: 'blur' }]
      }
    }
  },
  // 页面创建时自动加载验证码
  created() {
    this.getCaptcha()
  },
  methods: {
    // 核心:获取/刷新验证码
    getCaptcha() {
      getCaptchaImg().then(res => {
        this.captchaPath = res.data.captcha // 赋值验证码图片地址
        this.loginForm.uuid = res.data.uuid // 保存验证码唯一标识
        // 开发环境自动填充验证码
        if (process.env.NODE_ENV === 'development') {
          this.loginForm.captcha = res.data.code
        }
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.captcha-container {
  padding: 30px;
  background: #ffffff;
  width: 390px;
  border-radius: 5px;

  .captcha-img {
    width: 100px;
    height: 40px;
    margin-left: 8px;
    position: absolute;
    cursor: pointer;
  }
}
</style>

其中导入的验证码 API 的逻辑内容为:

javascript 复制代码
export function getCaptchaImg() {
  return request({
    url: '/captcha',
    method: 'get'
  })
}

后端逻辑代码示例:

java 复制代码
@RestController
public class LoginController {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 获取验证码
     *
     * @return
     */
    @GetMapping("/captcha")
    public Result getCaptcha() {
        // 借助工具包生成符合要求的验证码
        SpecCaptcha specCaptcha = new SpecCaptcha(130, 48, 4);
        // 获取到验证码图片的内容值并转大写
        String code = specCaptcha.text().toUpperCase();
        // 用uuid生成唯一的key,用于存储验证码
        String uuid = IdUtil.simpleUUID();
        // 往redis里存数据
        redisTemplate.opsForValue().set(uuid, code, 120, TimeUnit.SECONDS);
        // 往回组装数据
        HashMap<String, String> res = new HashMap<String, String>();
        res.put("uuid", uuid);
        // 获取Base64编码
        res.put("captcha", specCaptcha.toBase64());
        res.put("code", code);
        return Result.ok().put("data", res);
    }
}

Base64 编码的核心作用:

后端通过 easy-captcha 生成验证码图片后,会得到图片的二进制数据(字节流),Base64 编码能将这种二进制数据转换成可打印的文本字符串(避免二进制传输的乱码 / 解析问题),这段代码中 specCaptcha.toBase64() 会直接生成包含 Data URI 前缀(如data:image/png;base64,)的 Base64 字符串,前端拿到后无需手动拼接前缀,直接将这个字符串赋值给 <img> 标签的 src 属性,浏览器就能自动解码 Base64 字符串并渲染出验证码图片。

相关推荐
韭菜炒大葱2 小时前
现代前端开发工程化:Vue3 + Vite 带你从 0 到 1 搭建 Vue3 项目🚀
前端·vue.js·vite
老华带你飞2 小时前
志愿者服务管理|基于springboot 志愿者服务管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·spring
有意义2 小时前
让宠物打冰球!手把手教你用 Coze 多模态工作流 + Vue 3 打造 AI 拟人生成器
vue.js·前端工程化·coze
有点笨的蛋2 小时前
Vue3 项目:宠物照片变身冰球运动员的 AI 应用
前端·vue.js
汤姆yu2 小时前
基于springboot的宠物服务管理系统
java·spring boot·后端
鹿角片ljp2 小时前
智能家居控制系统Java实现
java·开发语言·智能家居
猿饵块2 小时前
python--锁
java·jvm·python
Charlie_Byte3 小时前
用 MurmurHash + Base62 生成短链接
java·后端
星辰落满衣3 小时前
股票实时交易数据之Python、Java等多种主流语言实例代码演示通过股票数据接口
java·开发语言·python