SpringBoot3整合Hutool-captcha實現(xiàn)圖形驗證碼
驗證碼需求分析:
1. 生成驗證碼,點擊圖片可進行刷新
2. 輸入驗證碼,點擊提交,驗證用戶輸入驗證碼是否正確
項目創(chuàng)建
首先創(chuàng)建項目這里使用的Spring boot 3 + JDK17,并引入相關(guān)依賴

pom.xml
<properties>
<java.version>17</java.version>
<hutool.version>5.8.26</hutool.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-captcha</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-bom</artifactId>
<version>${hutool.version}</version>
<type>pom</type>
<!-- 注意這里是import -->
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
import方式的使用說明
如果你想像Spring-Boot一樣引入Hutool,再由子模塊決定用到哪些模塊,你可以在父模塊中加入:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-bom</artifactId>
<version>${hutool.version}</version>
<type>pom</type>
<!-- 注意這里是import -->
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
在子模塊中就可以引入自己需要的模塊了:
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-captcha</artifactId>
</dependency>
使用import的方式,只會引入hutool-bom內(nèi)的dependencyManagement的配置,其它配置在這個引用方式下完全不起作用。
exclude方式
如果你引入的模塊比較多,但是某幾個模塊沒用,你可以:
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-bom</artifactId>
<version>${hutool.version}</version>
<!-- 加不加這句都能跑,區(qū)別只有是否告警 -->
<type>pom</type>
<exclusions>
<exclusion>
<groupId>cn.hutool</groupId>
<artifactId>hutool-system</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
這個配置會傳遞依賴hutool-bom內(nèi)所有dependencies的內(nèi)容,當前hutool-bom內(nèi)的dependencies全部設置了version,就意味著在maven resolve的時候hutool-bom內(nèi)就算存在dependencyManagement也不會產(chǎn)生任何作用。
定義接口:
1. 生成驗證碼,并返回
2. 校驗驗證碼是否正確
接口定義
1. 生成驗證碼
[URL]
GET /captcha/getCaptcha
[請求參數(shù)]
[響應]
{
"uuid": "fc2b40825f20470bb4f5d9868b33856f",
"img": "data:image/png;base64,issaxxxxxxxxgg=="
}
uuid 是為了方便在真實項目使用中做區(qū)分
2. 校驗驗證碼是否正確
[URL]
POST /captcha/check
[請求參數(shù)]
{"uuid":"43b4b30bf1134e9f8430507b7babd620","code":""}
[響應]
{
true
}
根據(jù)用戶輸入的驗證碼,校驗驗證碼是否正確,校驗成功,返回true;校驗失敗,返回false
定義 CaptchaController
@Slf4j
@RestController
@RequestMapping("/captcha")
@AllArgsConstructor
public class CaptchaController {
private final SysCaptchaService sysCaptchaService;
/**
* 生成驗證碼
*/
@GetMapping("/getCaptcha")
public CaptchaResult getCaptcha(HttpSession session) {
return sysCaptchaService.getCaptcha(session);
}
/**
* 驗證碼校驗
*
* @param param 驗證碼參數(shù)
*/
@PostMapping("/check")
public boolean checkCaptcha(@RequestBody CaptchaValidateParam param, HttpSession session) {
String uuid = param.getUuid();
String captcha = param.getCode();
if (StrUtil.isEmpty(uuid) || StrUtil.isEmpty(captcha)) {
log.error("驗證碼參數(shù)不能為空");
return false;
}
log.info("接收到驗證碼: uuId:{}, 驗證碼:{}", uuid, captcha);
// 參數(shù)校驗
return sysCaptchaService.validate(uuid, captcha, session);
}
}
由于當用戶輸入驗證碼時,我們需要進行校驗,因此,我們需要對生成的驗證碼進行存儲,同時,需要存儲驗證碼的生成時間,以便判斷驗證碼是否超時
public class Constants {
public static final String CAPTCHA_CODE = "code";
public static final String CAPTCHA_UUID = "uuid";
}
- SysCaptchaService
public interface SysCaptchaService {
/**
* 獲取驗證碼
*
* @param session
* @return
*/
CaptchaResult getCaptcha(HttpSession session);
/**
* 驗證碼效驗
*
* @param uuid
* @param code
* @param session
* @return
*/
boolean validate(String uuid, String code, HttpSession session);
}
- SysCaptchaServiceImpl
@Service
@RequiredArgsConstructor
@Slf4j
public class SysCaptchaServiceImpl implements SysCaptchaService {
private final CaptchaProperties captchaProperties;
private final CodeGenerator codeGenerator;
private final Font captchaFont;
@Override
public CaptchaResult getCaptcha(HttpSession session) {
String captchaType = captchaProperties.getType();
int width = captchaProperties.getWidth();
int height = captchaProperties.getHeight();
int interfereCount = captchaProperties.getInterfereCount();
int codeLength = captchaProperties.getCode().getLength();
AbstractCaptcha captcha;
if (CaptchaTypeEnums.CIRCLE.name().equalsIgnoreCase(captchaType)) {
captcha = CaptchaUtil.createCircleCaptcha(width, height, codeLength, interfereCount);
} else if (CaptchaTypeEnums.GIF.name().equalsIgnoreCase(captchaType)) {
captcha = CaptchaUtil.createGifCaptcha(width, height, codeLength);
} else if (CaptchaTypeEnums.LINE.name().equalsIgnoreCase(captchaType)) {
captcha = CaptchaUtil.createLineCaptcha(width, height, codeLength, interfereCount);
} else if (CaptchaTypeEnums.SHEAR.name().equalsIgnoreCase(captchaType)) {
captcha = CaptchaUtil.createShearCaptcha(width, height, codeLength, interfereCount);
} else {
throw new IllegalArgumentException("Invalid captcha type: " + captchaType);
}
captcha.setGenerator(codeGenerator);
captcha.setTextAlpha(captchaProperties.getTextAlpha());
captcha.setFont(captchaFont);
String code = captcha.getCode();
String imageBase64Data = captcha.getImageBase64Data();
// 驗證碼文本緩存至Redis,用于登錄校驗
String uuid = IdUtil.fastSimpleUUID();
session.setAttribute(Constants.CAPTCHA_CODE, code);
session.setAttribute(Constants.CAPTCHA_UUID, uuid);
return CaptchaResult.builder().img(imageBase64Data).uuid(uuid).build();
}
@Override
public boolean validate(String uuid, String code, HttpSession session) {
// session中獲取驗證碼
String captchaCode = (String) session.getAttribute(Constants.CAPTCHA_CODE);
return codeGenerator.verify(captchaCode, code);
}
將用戶輸入的驗證碼與存儲在 session 中的驗證碼進行對比,判斷其是否相同,若相同且在1min內(nèi),則驗證成功
前端代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
#inputCaptcha {
height: 30px;
vertical-align: middle;
}
#verificationCodeImg {
vertical-align: middle;
}
#checkCaptcha {
height: 40px;
width: 100px;
border: 1px solid #000;
border-radius: 5px;
margin-left: 10px;
vertical-align: middle;
}
</style>
</head>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<body>
<div id="app">
<h1>{{ message }}</h1>
<input type="text" v-model="inputCaptcha" id="inputCaptcha">
<img id="verificationCodeImg" :src="captchaData.img" alt="驗證碼" @click="refreshCaptcha" title="看不清?換一張"/>
<input type="button" value="提交" id="checkCaptcha" @click="checkCaptcha">
</div>
<script type="module">
import {createApp, ref, onMounted} from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
createApp({
setup() {
const message = ref('驗證碼校驗')
const inputCaptcha = ref('')
const captchaData = ref({
img: '',
uuid: ''
})
const refreshCaptcha = () => {
$.ajax({
url: '/captcha/getCaptcha',
type: 'GET',
success: function (data) {
captchaData.value = data
}
})
}
const checkCaptcha = () => {
const dataFrom = {
uuid: captchaData.value.uuid,
code: inputCaptcha.value
}
$.ajax({
url: '/captcha/check',
type: 'POST',
headers: {
'Content-Type': 'application/json'
},
data: JSON.stringify(dataFrom),
success: function (data) {
if (data) {
alert('驗證碼正確')
refreshCaptcha()
} else {
alert('驗證碼錯誤')
refreshCaptcha()
}
}
})
}
// 頁面加載完成后,刷新驗證碼
onMounted(() => {
refreshCaptcha()
})
return {
message,
captchaData,
inputCaptcha,
refreshCaptcha,
checkCaptcha
}
}
}).mount('#app')
</script>
</body>
</html>
驗證成功:

驗證失?。?/p>

為讓驗證碼有多樣性,這里將驗證的生成放入了application.yml配置文件中,內(nèi)容如下:
# 驗證碼配置
captcha:
# 驗證碼類型 circle-圓圈干擾驗證碼|gif-Gif驗證碼|line-干擾線驗證碼|shear-扭曲干擾驗證碼
type: circle
# 驗證碼寬度
width: 130
# 驗證碼高度
height: 48
# 驗證碼干擾元素個數(shù)
interfere-count: 2
# 文本透明度(0.0-1.0)
text-alpha: 0.8
# 驗證碼字符配置
code:
# 驗證碼字符類型 math-算術(shù)|random-隨機字符
type: math
# 驗證碼字符長度,type=算術(shù)時,表示運算位數(shù)(1:個位數(shù)運算 2:十位數(shù)運算);type=隨機字符時,表示字符個數(shù)
length: 1
# 驗證碼字體
font:
# 字體名稱 Dialog|DialogInput|Monospaced|Serif|SansSerif
name: SansSerif
# 字體樣式 0-普通|1-粗體|2-斜體
weight: 1
# 字體大小
size: 20
# 驗證碼有效期(秒)
expire-seconds: 120
以上就是SpringBoot3整合Hutool-captcha實現(xiàn)圖形驗證碼的詳細內(nèi)容,更多關(guān)于SpringBoot3 Hutool-captcha驗證碼的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java8新特性stream和parallelStream區(qū)別
這篇文章主要介紹了Java8新特性stream和parallelStream區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-11-11
FastJson踩坑:@JsonField在反序列化時失效的解決
這篇文章主要介紹了FastJson踩坑:@JsonField在反序列化時失效的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06
深入解析Jdk8中Stream流的使用讓你脫離for循環(huán)
這篇文章主要介紹了Jdk8中Stream流的使用,讓你脫離for循環(huán),本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2020-02-02
spring boot空屬性賦值問題與aspect日志實現(xiàn)方法
這篇文章主要介紹了spring boot空屬性賦值問題與aspect日志實現(xiàn)方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-08-08
restTemplate未設置連接數(shù)導致服務雪崩問題以及解決
面對線上問題,仔細分析原因,及時調(diào)整配置,能有效解決問題,本文詳細描述了線上遇到流量突增引發(fā)的問題,通過查看代碼和連接池信息,分析出問題的原因是連接池滿了,連接池大小配置不足以應對大并發(fā)流量,通過調(diào)整連接池大小配置2024-10-10
SpringWebMVC的常用注解及應用分層架構(gòu)詳解
這篇文章主要介紹了SpringWebMVC的常用注解及應用分層架構(gòu),SpringWebMVC是基于ServletAPI構(gòu)建的原始Web框架,從?開始就包含在Spring框架中,感興趣的朋友可以參考下2024-05-05
SpringBoot集成MQTT實現(xiàn)交互服務通信
MQTT非常適用于物聯(lián)網(wǎng)領(lǐng)域,本文主要介紹了SpringBoot集成MQTT實現(xiàn)交互服務通信,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2024-08-08

