知不足而奋进 望远山而前行

验证码图片生成 hutool-captcha

2024-04-06  本文已影响0人  不返y

一、使用的依赖

此处需要引入的依赖hutool-captcha

<!-- 获取图形验证码 -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-captcha</artifactId>
    <version>5.8.18</version>
</dependency>

注:hutool-captcha已经包含在了 hutool-all 中,也可以直接引入 hutool-all。

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

二、使用依赖

生成验证码的工具是 CaptchaUtil,基本使用方式如下:

/**
 * 获取验证码
 */
@Test
public void getCaptcha() throws FileNotFoundException {

    //生成带有直线干扰的验证码图片
    LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(300, 100, 4, 20);//指定(宽,高,验证码数量,干扰项数量)
    
    //获取验证码的信息
    System.out.println(lineCaptcha.getCode());//验证码的文本信息,用于校对
    
    //将验证码图片转换为base64格式字符串
    System.out.println("不带数据格式前缀:" + lineCaptcha.getImageBase64());//不带数据格式前缀
    System.out.println("带数据格式前缀:" +  lineCaptcha.getImageBase64Data());//带数据格式前缀

    //保存验证码图片
    lineCaptcha.write("D:\\@Information\\ceshia\\1.png");//1传保存路径
    lineCaptcha.write(new File("D:\\@Information\\ceshia\\2.png"));//2传文件
    lineCaptcha.write(new FileOutputStream(new File("D:\\@Information\\ceshia\\3.png")));//3传输出流

    boolean b = lineCaptcha.verify("1wcc");//校验用户输入的验证码, b为true表示验证码正确
    
}
createLineCaptcha验证码生成

关于base64图片:base64可以将图片转为字符串,将验证码图片以base64格式发送。可以减少http请求次数,同时将图片和对应的key发送到前端页面,而服务器上只需要保存验证码的值和key用来验证即可。

在上例中lineCaptcha.getImageBase64()获取的是不带前缀的base64格式图片,发送页面上去后需要手动拼接数据格式前缀才能正常识别图片。而lineCaptcha.getImageBase64Data()获取的是已经带上数据前缀的字符串,不许要进行额外的处理。


CaptchaUtil验证码生成工具不只是有createLineCaptcha一个方法,还有createCircleCaptchacreateShearCaptchacreateGifCaptcha等不同的方法。

它们的区别就是验证码的干扰项不一样。具体使用和区别可以简单浏览下:

/**
 * 获取验证码`createCircleCaptcha`
 */
@Test
public void getCaptcha() throws FileNotFoundException {
    //生成随机圆圈干扰验证码图片
    CircleCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(300, 100, 4, 20);//指定(宽,高,验证码数量,干扰项数量)
    //获取验证码的信息
    System.out.println(circleCaptcha.getCode());//验证码的文本信息,用于校对
    //将验证码图片转换为base64格式字符串
    System.out.println("不带数据格式前缀:" + circleCaptcha.getImageBase64());//不带数据格式前缀
    System.out.println("带数据格式前缀:" +  circleCaptcha.getImageBase64Data());//带数据格式前缀

    //保存验证码图片
    circleCaptcha.write("D:\\@Information\\ceshia\\1.png");//传保存路径
    circleCaptcha.write(new File("D:\\@Information\\ceshia\\2.png"));//传文件
    circleCaptcha.write(new FileOutputStream(new File("D:\\@Information\\ceshia\\3.png")));//传输出流

    boolean b = lineCaptcha.verify("g2zf");//校验用户输入的验证码, b为true表示验证码正确
}
createCircleCaptcha验证码生成
/**
 * 获取验证码`createShearCaptcha`
 */
@Test
public void getCaptcha() throws FileNotFoundException {
    //生成斜线遮挡的验证码图片
    ShearCaptcha shearCaptcha = CaptchaUtil.createShearCaptcha(300, 100, 4, 1);//指定(宽,高,验证码数量,干扰项斜线的宽度)
    //获取验证码的信息
    System.out.println(shearCaptcha.getCode());//验证码的文本信息,用于校对
    //将验证码图片转换为base64格式字符串
    System.out.println("不带数据格式前缀:" + shearCaptcha.getImageBase64());//不带数据格式前缀
    System.out.println("带数据格式前缀:" + shearCaptcha.getImageBase64Data());//带数据格式前缀

    //保存验证码图片
    shearCaptcha.write("D:\\@Information\\ceshia\\1.png");//传保存路径
    shearCaptcha.write(new File("D:\\@Information\\ceshia\\2.png"));//传文件
    shearCaptcha.write(new FileOutputStream(new File("D:\\@Information\\ceshia\\3.png")));//传输出流

     boolean b = lineCaptcha.verify("zyhv");//校验用户输入的验证码, b为true表示验证码正确
}
createShearCaptcha验证码生成
/**
 * 获取验证码`createGifCaptcha` 注意,这里生成的图片后缀要是动图.gif的格式
 */
@Test
public void getCaptcha() throws FileNotFoundException {
    //生成动图验证码图片
    GifCaptcha gifCaptcha = CaptchaUtil.createGifCaptcha(300, 100, 4);//指定(宽,高,验证码数量)
    //获取验证码的信息
    System.out.println(gifCaptcha.getCode());//验证码的文本信息,用于校对
    //将验证码图片转换为base64格式字符串
    System.out.println("不带数据格式前缀:" + gifCaptcha.getImageBase64());//不带数据格式前缀
    System.out.println("带数据格式前缀:" + gifCaptcha.getImageBase64Data());//带数据格式前缀

    //保存验证码图片
    gifCaptcha.write("D:\\@Information\\ceshia\\1.gif");//传保存路径
    gifCaptcha.write(new File("D:\\@Information\\ceshia\\2.gif"));//传文件
    gifCaptcha.write(new FileOutputStream(new File("D:\\@Information\\ceshia\\3.gif")));//传输出流

    boolean b = lineCaptcha.verify("zjsx");//校验用户输入的验证码, b为true表示验证码正确
}
createGifCaptcha验证码生成

三、项目中的使用

在前后端分离的场景中,后端向前端发送验证码。(涉及到使用redis存储验证码,和lombok相关,不知道的可以先不看啦)

创建:下面使用的是CaptchaUtil.createGifCaptcha方法创建的动图验证码,通过uuid生成验证码的key。在通过redis缓存验证码的key、value后,将图片转成base64字符串和key一起发送出去。

验证:验证没有使用自带的lineCaptcha.verify()方法,而是通过redis手动获取信息检查验证。如果redis取出验证码信息的时候出现异常,即为验证失败。

/**
 * 获取验证码信息
 *
 * @return CaptchaVO对象,包含一个随机验证码图片及其对应的key
 */
public CaptchaVO getGifCaptcha() {
    //生成验证码图片, 定义图形验证码的长、宽、验证码字符数(这里采用的是动图验证码)
    GifCaptcha captcha = CaptchaUtil.createGifCaptcha(300, 100, 4);

    //生成验证码唯一标识,这里主要是为了临时的区分用户端的,验证码唯一标识这里采用的是uuid生成
    String captchaKey = UUID.randomUUID().toString().replace("-","");

    //获得图片,base64格式
    String image = captcha.getImageBase64();

    //获取验证码图片上的字母,即验证码的答案
    String captchaValue = captcha.getCode();

    //将验证码信息存入redis
    redisTemplate.opsForValue().set(
            captchaKey, captchaValue, //设置数据
            120, TimeUnit.SECONDS); //设置有效时间

    //封装对象,返回数据
    return CaptchaVO.builder()
            .msgCodeUrl(image) //验证码图片
            .keyCode(captchaKey) //验证码图片对应key
            .build();
}

/**
* 检查验证码的正确性
*
* @param captchaKey 当前用户的验证码的key
* @param UserCaptchaValue 用户填写的验证码信息
*/
public void checkMsgCode(String captchaKey, String UserCaptchaValue) {
  if (captchaKey != null && UserCaptchaValue != null) { //非空判断
    try {
      String trueCaptchaValue =(String)redisTemplate.opsForValue().get(captchaKey);//根据key获取真正的验证码信息
      redisTemplate.delete(captchaKey);//删除验证码信息,此条验证码作废
      if (trueCaptchaValue != null && UserCaptchaValue.compareToIgnoreCase(trueCaptchaValue) == 0) {
        //验证码正确,退出
        return;
      }
    } catch (Exception ignored) {
      //忽略异常,
    }
  }
  throw new RuntimeException("验证码错误或已过期");//验证码不正确,抛出异常
}
上一篇 下一篇

猜你喜欢

热点阅读