Skip to content
广告❤️成为赞助商

图片验证码的作用

图片验证码,利用图片生成技术,把文本内容绘制在图片中,用户识别内容与图片内容一致认为验证通过。

该技术的主要作用是为了防止爬虫模拟操作获取系统敏感数据甚至攻击,图片验证码有一定的预防作用,有防就有攻黑客利用图片识别技术 破解验证码,为此图片验证会设置各种干扰参数增加破解难度,近些年出现拼图点图验证,本质都是一样的增加破解验证难度。

实现一个图片验证码

  • 安装依赖

  • Apache Maven

<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>kisso</artifactId>
  <version>3.8.1</version>
</dependency>
  • Gradle DSL
implementation("com.baomidou:kisso:3.8.1")
  • 注入图片验证码
@Bean
public ImageCaptcha imageCaptcha() {
    ImageCaptcha imageCaptcha = ImageCaptcha.getInstance();
    // 干扰量 1
    imageCaptcha.setInterfere(1);
    // 验证码内容长度 4 位
    imageCaptcha.setLength(4);
    // Gif 验证码
    // imageCaptcha.setGif(true);
    // 验证码存储处理类,默认存在在 session 实现类 CaptchaStoreSession 仅适用单机
    // 分布式可以采用 Redis 处理,例如 RedisCaptchaStore 实现 ICaptchaStore 接口
    // imageCaptcha.setCaptchaStore(new CaptchaStoreRedis());
    return imageCaptcha;
}

配置 imageCaptcha 属性说明

名称说明
gif是否为 GIF 验证码
font字体
rgbArrRGB 颜色数组
interfere干扰量
interfereColor干扰色默认随机
color验证码颜色默认随机
length验证码随机字符长度
width验证码显示宽度
height验证码显示高度
suffix图片后缀
randomType验证码类型:MIX 字母数字混合、NUMBER 数字、CHARACTER 字母、CHINESE 汉字
chineseUnicode常用汉字
captchaStore图片验证码票据存储接口 ICaptchaStore
ignoreCase是否忽略验证内容大小写,默认 true
  • 效果图

png

gif

  • Spring Boot 图片验证码生成验证
@RestController
@RequestMapping("/v1/captcha")
public class CaptchaController {
    @Resource
    protected HttpServletRequest request;
    @Resource
    protected HttpServletResponse response;
    @Resource
    private ICaptcha captcha;

    // 生成验证,例如:http://localhost:8088/v1/captcha/image?ticket=123456
    @GetMapping("/image")
    public void image(String ticket) {
        try {
            // 验证码信息存放在缓存中,key = ticket 、 value = 验证码文本内容
            captcha.generate(request, response.getOutputStream(), ticket);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 校验图片验证码
    @PostMapping("/verification")
    public boolean verification(String ticket, String code) {
        // ticket 为生成验证码的票据, code 为图片验证码文本内容
        return captcha.verification(request, ticket, code);
    }
}
  • 前端调用
<img src="http://localhost:8088/v1/captcha/image?ticket=123456" width="130px" height="48px" />

注意

  1. 验证码 ticket 票据可以是前端生成也可以是后端生成( 可以是 UUID、时间戳 ),需要确保每次都不一样。
  2. 默认验证码实现 session 存储只适用于单机、分布式情况请自行实现 ICaptchaStore 接口注入、存储在分布式介质中例如 Redis 缓存。

接入第三方验证码库 EasyCaptcha

该验证码库EasyCaptcha还是挺不错的 Java 图形验证码库,支持gif、中文、算术等类型,有些字体效果也挺漂亮, 喜欢轻量级可以直接采用 kisso 内置的实现,喜欢 EasyCaptcha 库的可以按照如下方法接入。

  • 安装 EasyCaptcha 依賴

  • Apache Maven

<dependency>
  <groupId>com.github.whvcse</groupId>
  <artifactId>easy-captcha</artifactId>
  <version>1.6.2</version>
</dependency>
  • Gradle DSL
implementation("com.github.whvcse:easy-captcha:1.6.2")
  • 实现验证码接口 ICaptcha
public class EasyCaptcha implements ICaptcha {
    protected ICaptchaStore captchaStore;

    @Override
    public void generate(HttpServletRequest request, OutputStream outputStream, String ticket) throws IOException {
        SpecCaptcha specCaptcha = new SpecCaptcha(130, 48, 5);
        specCaptcha.out(outputStream);
        this.getCaptchaStore(request).put(ticket, specCaptcha.text());
    }

    @Override
    public boolean verification(HttpServletRequest request, String ticket, String captcha) {
        String content = this.getCaptchaStore(request).get(ticket);
        return null != content ? content.equalsIgnoreCase(captcha) : false;
    }


    private ICaptchaStore getCaptchaStore(HttpServletRequest request) {
        return null == this.captchaStore ? new CaptchaStoreSession(request) : this.captchaStore;
    }
}
  • 注入图片验证码 EasyCaptcha 实现
/**
 * 注入图片验证码
 */
@Bean
public EasyCaptcha easyCaptcha() {
  return new EasyCaptcha();
}
  • 效果图

png

具体 使用逻辑参考上文 Spring Boot 图片验证码生成验证

接入第三方验证码库 Google Kaptcha

该验证库为 Google 验证码库老牌了,目前中央仓库没有官方坐标,可以去官网http://code.google.com/p/kaptcha/下载jar,或者在pom.xml中导入 ,这里推荐使用第三方上传的坐标:

<dependency>
    <groupId>com.github.penggle</groupId>
    <artifactId>kaptcha</artifactId>
    <version>2.3.2</version>
</dependency>
  • Gradle DSL
implementation("com.github.penggle:kaptcha:2.3.2")
  • 实现验证码接口 ICaptcha
@Component // 这里申明注入,当前也可以上面一样 bean 注入
public class Kaptcha implements ICaptcha {
    protected ICaptchaStore captchaStore;

    @Override
    public void generate(HttpServletRequest request, OutputStream outputStream, String ticket) throws IOException {
        // KAPTCHA.createText() 这里可以生成文本,也可以配置自定义 kaptcha.word.impl 文本渲染器
        // 这里你自己写一个随机生成文本算法即可
        String text = "3x9=?";
        ImageIO.write(KAPTCHA.createImage(text), "png", outputStream);
        // 存储 ticket 作为 key 验证文本作为 value 这里是图片验证希望得到的实际结果文本
        this.getCaptchaStore(request).put(ticket, "27");
    }

    @Override
    public boolean verification(HttpServletRequest request, String ticket, String captcha) {
        String content = this.getCaptchaStore(request).get(ticket);
        return null != content ? content.equalsIgnoreCase(captcha) : false;
    }

    private ICaptchaStore getCaptchaStore(HttpServletRequest request) {
        return null == this.captchaStore ? new CaptchaStoreSession(request) : this.captchaStore;
    }

    private static final DefaultKaptcha KAPTCHA;

    static {
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        Properties properties = new Properties();
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
        properties.setProperty(KAPTCHA_IMAGE_WIDTH, "130");
        properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "48");
        Config config = new Config(properties);
        defaultKaptcha.setConfig(config);
        KAPTCHA = defaultKaptcha;
    }
}
  • 效果图

png

  • 配置属性

Kaptcha 是一个可高度配置的实用验证码生成工具,可自由配置的选项如:

名称默认说明
kaptcha.borderyes图片边框,合法值:yes , no
kaptcha.border.colorblack边框颜色,合法值: r,g,b (and optional alpha) 或者 white,black,blue
kaptcha.image.width200图片宽
kaptcha.image.height50图片高
kaptcha.producer.implcom.google.code.kaptcha.impl.DefaultKaptcha图片实现类
kaptcha.textproducer.implcom.google.code.kaptcha.text.impl.DefaultTextCreator文本实现类
kaptcha.textproducer.char.string文本集合,验证码值从此集合中获取abcde2345678gfynmnpwx
kaptcha.textproducer.char.length5验证码长度
kaptcha.textproducer.font.namesArial, Courier字体
kaptcha.textproducer.font.size40px字体大小
kaptcha.textproducer.font.colorblack字体颜色,合法值: r,g,b 或者 white,black,blue
kaptcha.textproducer.char.space2文字间隔
kaptcha.noise.implcom.google.code.kaptcha.impl.DefaultNoise干扰实现类
kaptcha.noise.colorblack干扰 颜色,合法值: r,g,b 或者 white,black,blue
kaptcha.obscurificator.implcom.google.code.kaptcha.impl.WaterRipple图片样式:
水纹 com.google.code.kaptcha.impl.WaterRipple 鱼眼 com.google.code.kaptcha.impl.FishEyeGimpy 阴影 com.google.code.kaptcha.impl.ShadowGimpy
kaptcha.background.implcom.google.code.kaptcha.impl.DefaultBackground背景实现类
kaptcha.background.clear.fromlight grey背景颜色渐变,开始颜色
kaptcha.background.clear.towhite背景颜色渐变, 结束颜色
kaptcha.word.implcom.google.code.kaptcha.text.impl.DefaultWordRenderer文字渲染器
kaptcha.session.keyKAPTCHA_SESSION_KEYsession key
kaptcha.session.dateKAPTCHA_SESSION_DATEsession date

开源行为式验证码

行为式验证码是一种较为流行的验证码。从字面来理解,就是通过用户的操作行为来完成验证,而无需去读懂扭曲的图片文字。常见的有两种:拖动式与点触式。

基于 Vue3 + Vite + Canvas 开发的滑块验证码 文档地址 适用于各种表单提交前的验证。

每个人都是架构师