驗(yàn)證碼圖片生成 hutool-captcha

一、使用的依賴(lài)

此處需要引入的依賴(lài)hutool-captcha

<!-- 獲取圖形驗(yàn)證碼 -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-captcha</artifactId>
    <version>5.8.18</version>
</dependency>

注:hutool-captcha已經(jīng)包含在了 hutool-all 中,也可以直接引入 hutool-all。

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

二、使用依賴(lài)

生成驗(yàn)證碼的工具是 CaptchaUtil,基本使用方式如下:

/**
 * 獲取驗(yàn)證碼
 */
@Test
public void getCaptcha() throws FileNotFoundException {

    //生成帶有直線(xiàn)干擾的驗(yàn)證碼圖片
    LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(300, 100, 4, 20);//指定(寬,高,驗(yàn)證碼數(shù)量,干擾項(xiàng)數(shù)量)
    
    //獲取驗(yàn)證碼的信息
    System.out.println(lineCaptcha.getCode());//驗(yàn)證碼的文本信息,用于校對(duì)
    
    //將驗(yàn)證碼圖片轉(zhuǎn)換為base64格式字符串
    System.out.println("不帶數(shù)據(jù)格式前綴:" + lineCaptcha.getImageBase64());//不帶數(shù)據(jù)格式前綴
    System.out.println("帶數(shù)據(jù)格式前綴:" +  lineCaptcha.getImageBase64Data());//帶數(shù)據(jù)格式前綴

    //保存驗(yàn)證碼圖片
    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");//校驗(yàn)用戶(hù)輸入的驗(yàn)證碼, b為true表示驗(yàn)證碼正確
    
}
createLineCaptcha驗(yàn)證碼生成

關(guān)于base64圖片:base64可以將圖片轉(zhuǎn)為字符串,將驗(yàn)證碼圖片以base64格式發(fā)送??梢詼p少http請(qǐng)求次數(shù),同時(shí)將圖片和對(duì)應(yīng)的key發(fā)送到前端頁(yè)面,而服務(wù)器上只需要保存驗(yàn)證碼的值和key用來(lái)驗(yàn)證即可。

在上例中lineCaptcha.getImageBase64()獲取的是不帶前綴的base64格式圖片,發(fā)送頁(yè)面上去后需要手動(dòng)拼接數(shù)據(jù)格式前綴才能正常識(shí)別圖片。而lineCaptcha.getImageBase64Data()獲取的是已經(jīng)帶上數(shù)據(jù)前綴的字符串,不許要進(jìn)行額外的處理。


CaptchaUtil驗(yàn)證碼生成工具不只是有createLineCaptcha一個(gè)方法,還有createCircleCaptcha、createShearCaptchacreateGifCaptcha等不同的方法。

它們的區(qū)別就是驗(yàn)證碼的干擾項(xiàng)不一樣。具體使用和區(qū)別可以簡(jiǎn)單瀏覽下:

/**
 * 獲取驗(yàn)證碼`createCircleCaptcha`
 */
@Test
public void getCaptcha() throws FileNotFoundException {
    //生成隨機(jī)圓圈干擾驗(yàn)證碼圖片
    CircleCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(300, 100, 4, 20);//指定(寬,高,驗(yàn)證碼數(shù)量,干擾項(xiàng)數(shù)量)
    //獲取驗(yàn)證碼的信息
    System.out.println(circleCaptcha.getCode());//驗(yàn)證碼的文本信息,用于校對(duì)
    //將驗(yàn)證碼圖片轉(zhuǎn)換為base64格式字符串
    System.out.println("不帶數(shù)據(jù)格式前綴:" + circleCaptcha.getImageBase64());//不帶數(shù)據(jù)格式前綴
    System.out.println("帶數(shù)據(jù)格式前綴:" +  circleCaptcha.getImageBase64Data());//帶數(shù)據(jù)格式前綴

    //保存驗(yàn)證碼圖片
    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");//校驗(yàn)用戶(hù)輸入的驗(yàn)證碼, b為true表示驗(yàn)證碼正確
}
createCircleCaptcha驗(yàn)證碼生成

/**
 * 獲取驗(yàn)證碼`createShearCaptcha`
 */
@Test
public void getCaptcha() throws FileNotFoundException {
    //生成斜線(xiàn)遮擋的驗(yàn)證碼圖片
    ShearCaptcha shearCaptcha = CaptchaUtil.createShearCaptcha(300, 100, 4, 1);//指定(寬,高,驗(yàn)證碼數(shù)量,干擾項(xiàng)斜線(xiàn)的寬度)
    //獲取驗(yàn)證碼的信息
    System.out.println(shearCaptcha.getCode());//驗(yàn)證碼的文本信息,用于校對(duì)
    //將驗(yàn)證碼圖片轉(zhuǎn)換為base64格式字符串
    System.out.println("不帶數(shù)據(jù)格式前綴:" + shearCaptcha.getImageBase64());//不帶數(shù)據(jù)格式前綴
    System.out.println("帶數(shù)據(jù)格式前綴:" + shearCaptcha.getImageBase64Data());//帶數(shù)據(jù)格式前綴

    //保存驗(yàn)證碼圖片
    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");//校驗(yàn)用戶(hù)輸入的驗(yàn)證碼, b為true表示驗(yàn)證碼正確
}
createShearCaptcha驗(yàn)證碼生成

/**
 * 獲取驗(yàn)證碼`createGifCaptcha` 注意,這里生成的圖片后綴要是動(dòng)圖.gif的格式
 */
@Test
public void getCaptcha() throws FileNotFoundException {
    //生成動(dòng)圖驗(yàn)證碼圖片
    GifCaptcha gifCaptcha = CaptchaUtil.createGifCaptcha(300, 100, 4);//指定(寬,高,驗(yàn)證碼數(shù)量)
    //獲取驗(yàn)證碼的信息
    System.out.println(gifCaptcha.getCode());//驗(yàn)證碼的文本信息,用于校對(duì)
    //將驗(yàn)證碼圖片轉(zhuǎn)換為base64格式字符串
    System.out.println("不帶數(shù)據(jù)格式前綴:" + gifCaptcha.getImageBase64());//不帶數(shù)據(jù)格式前綴
    System.out.println("帶數(shù)據(jù)格式前綴:" + gifCaptcha.getImageBase64Data());//帶數(shù)據(jù)格式前綴

    //保存驗(yàn)證碼圖片
    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");//校驗(yàn)用戶(hù)輸入的驗(yàn)證碼, b為true表示驗(yàn)證碼正確
}
createGifCaptcha驗(yàn)證碼生成

三、項(xiàng)目中的使用

在前后端分離的場(chǎng)景中,后端向前端發(fā)送驗(yàn)證碼。(涉及到使用redis存儲(chǔ)驗(yàn)證碼,和lombok相關(guān),不知道的可以先不看啦)

創(chuàng)建:下面使用的是CaptchaUtil.createGifCaptcha方法創(chuàng)建的動(dòng)圖驗(yàn)證碼,通過(guò)uuid生成驗(yàn)證碼的key。在通過(guò)redis緩存驗(yàn)證碼的key、value后,將圖片轉(zhuǎn)成base64字符串和key一起發(fā)送出去。

驗(yàn)證:驗(yàn)證沒(méi)有使用自帶的lineCaptcha.verify()方法,而是通過(guò)redis手動(dòng)獲取信息檢查驗(yàn)證。如果redis取出驗(yàn)證碼信息的時(shí)候出現(xiàn)異常,即為驗(yàn)證失敗。

/**
 * 獲取驗(yàn)證碼信息
 *
 * @return CaptchaVO對(duì)象,包含一個(gè)隨機(jī)驗(yàn)證碼圖片及其對(duì)應(yīng)的key
 */
public CaptchaVO getGifCaptcha() {
    //生成驗(yàn)證碼圖片, 定義圖形驗(yàn)證碼的長(zhǎng)、寬、驗(yàn)證碼字符數(shù)(這里采用的是動(dòng)圖驗(yàn)證碼)
    GifCaptcha captcha = CaptchaUtil.createGifCaptcha(300, 100, 4);

    //生成驗(yàn)證碼唯一標(biāo)識(shí),這里主要是為了臨時(shí)的區(qū)分用戶(hù)端的,驗(yàn)證碼唯一標(biāo)識(shí)這里采用的是uuid生成
    String captchaKey = UUID.randomUUID().toString().replace("-","");

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

    //獲取驗(yàn)證碼圖片上的字母,即驗(yàn)證碼的答案
    String captchaValue = captcha.getCode();

    //將驗(yàn)證碼信息存入redis
    redisTemplate.opsForValue().set(
            captchaKey, captchaValue, //設(shè)置數(shù)據(jù)
            120, TimeUnit.SECONDS); //設(shè)置有效時(shí)間

    //封裝對(duì)象,返回?cái)?shù)據(jù)
    return CaptchaVO.builder()
            .msgCodeUrl(image) //驗(yàn)證碼圖片
            .keyCode(captchaKey) //驗(yàn)證碼圖片對(duì)應(yīng)key
            .build();
}

/**
* 檢查驗(yàn)證碼的正確性
*
* @param captchaKey 當(dāng)前用戶(hù)的驗(yàn)證碼的key
* @param UserCaptchaValue 用戶(hù)填寫(xiě)的驗(yàn)證碼信息
*/
public void checkMsgCode(String captchaKey, String UserCaptchaValue) {
  if (captchaKey != null && UserCaptchaValue != null) { //非空判斷
    try {
      String trueCaptchaValue =(String)redisTemplate.opsForValue().get(captchaKey);//根據(jù)key獲取真正的驗(yàn)證碼信息
      redisTemplate.delete(captchaKey);//刪除驗(yàn)證碼信息,此條驗(yàn)證碼作廢
      if (trueCaptchaValue != null && UserCaptchaValue.compareToIgnoreCase(trueCaptchaValue) == 0) {
        //驗(yàn)證碼正確,退出
        return;
      }
    } catch (Exception ignored) {
      //忽略異常,
    }
  }
  throw new RuntimeException("驗(yàn)證碼錯(cuò)誤或已過(guò)期");//驗(yàn)證碼不正確,拋出異常
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容