SpringBoot3整合Hutool-captcha實(shí)現(xiàn)圖形驗(yàn)證碼
驗(yàn)證碼需求分析:
1. 生成驗(yàn)證碼,點(diǎn)擊圖片可進(jìn)行刷新
2. 輸入驗(yàn)證碼,點(diǎn)擊提交,驗(yàn)證用戶輸入驗(yàn)證碼是否正確
項(xiàng)目創(chuàng)建
首先創(chuàng)建項(xià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方式的使用說(shuō)明
如果你想像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的方式,只會(huì)引入hutool-bom內(nèi)的dependencyManagement的配置,其它配置在這個(gè)引用方式下完全不起作用。
exclude方式
如果你引入的模塊比較多,但是某幾個(gè)模塊沒(méi)用,你可以:
<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>
這個(gè)配置會(huì)傳遞依賴hutool-bom內(nèi)所有dependencies的內(nèi)容,當(dāng)前hutool-bom內(nèi)的dependencies全部設(shè)置了version,就意味著在maven resolve的時(shí)候hutool-bom內(nèi)就算存在dependencyManagement也不會(huì)產(chǎn)生任何作用。
定義接口:
1. 生成驗(yàn)證碼,并返回
2. 校驗(yàn)驗(yàn)證碼是否正確
接口定義
1. 生成驗(yàn)證碼 [URL] GET /captcha/getCaptcha [請(qǐng)求參數(shù)] [響應(yīng)] { "uuid": "fc2b40825f20470bb4f5d9868b33856f", "img": "data:image/png;base64,issaxxxxxxxxgg==" } uuid 是為了方便在真實(shí)項(xiàng)目使用中做區(qū)分
2. 校驗(yàn)驗(yàn)證碼是否正確 [URL] POST /captcha/check [請(qǐng)求參數(shù)] {"uuid":"43b4b30bf1134e9f8430507b7babd620","code":""} [響應(yīng)] { true } 根據(jù)用戶輸入的驗(yàn)證碼,校驗(yàn)驗(yàn)證碼是否正確,校驗(yàn)成功,返回true;校驗(yàn)失敗,返回false
定義 CaptchaController
@Slf4j @RestController @RequestMapping("/captcha") @AllArgsConstructor public class CaptchaController { private final SysCaptchaService sysCaptchaService; /** * 生成驗(yàn)證碼 */ @GetMapping("/getCaptcha") public CaptchaResult getCaptcha(HttpSession session) { return sysCaptchaService.getCaptcha(session); } /** * 驗(yàn)證碼校驗(yàn) * * @param param 驗(yàn)證碼參數(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("驗(yàn)證碼參數(shù)不能為空"); return false; } log.info("接收到驗(yàn)證碼: uuId:{}, 驗(yàn)證碼:{}", uuid, captcha); // 參數(shù)校驗(yàn) return sysCaptchaService.validate(uuid, captcha, session); } }
由于當(dāng)用戶輸入驗(yàn)證碼時(shí),我們需要進(jìn)行校驗(yàn),因此,我們需要對(duì)生成的驗(yàn)證碼進(jìn)行存儲(chǔ),同時(shí),需要存儲(chǔ)驗(yàn)證碼的生成時(shí)間,以便判斷驗(yàn)證碼是否超時(shí)
public class Constants { public static final String CAPTCHA_CODE = "code"; public static final String CAPTCHA_UUID = "uuid"; }
- SysCaptchaService
public interface SysCaptchaService { /** * 獲取驗(yàn)證碼 * * @param session * @return */ CaptchaResult getCaptcha(HttpSession session); /** * 驗(yàn)證碼效驗(yàn) * * @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(); // 驗(yàn)證碼文本緩存至Redis,用于登錄校驗(yàn) 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中獲取驗(yàn)證碼 String captchaCode = (String) session.getAttribute(Constants.CAPTCHA_CODE); return codeGenerator.verify(captchaCode, code); }
將用戶輸入的驗(yàn)證碼與存儲(chǔ)在 session 中的驗(yàn)證碼進(jìn)行對(duì)比,判斷其是否相同,若相同且在1min內(nèi),則驗(yàn)證成功
前端代碼
<!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="驗(yàn)證碼" @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('驗(yàn)證碼校驗(yàn)') 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('驗(yàn)證碼正確') refreshCaptcha() } else { alert('驗(yàn)證碼錯(cuò)誤') refreshCaptcha() } } }) } // 頁(yè)面加載完成后,刷新驗(yàn)證碼 onMounted(() => { refreshCaptcha() }) return { message, captchaData, inputCaptcha, refreshCaptcha, checkCaptcha } } }).mount('#app') </script> </body> </html>
驗(yàn)證成功:
驗(yàn)證失?。?/p>
為讓驗(yàn)證碼有多樣性,這里將驗(yàn)證的生成放入了application.yml
配置文件中,內(nèi)容如下:
# 驗(yàn)證碼配置 captcha: # 驗(yàn)證碼類型 circle-圓圈干擾驗(yàn)證碼|gif-Gif驗(yàn)證碼|line-干擾線驗(yàn)證碼|shear-扭曲干擾驗(yàn)證碼 type: circle # 驗(yàn)證碼寬度 width: 130 # 驗(yàn)證碼高度 height: 48 # 驗(yàn)證碼干擾元素個(gè)數(shù) interfere-count: 2 # 文本透明度(0.0-1.0) text-alpha: 0.8 # 驗(yàn)證碼字符配置 code: # 驗(yàn)證碼字符類型 math-算術(shù)|random-隨機(jī)字符 type: math # 驗(yàn)證碼字符長(zhǎng)度,type=算術(shù)時(shí),表示運(yùn)算位數(shù)(1:個(gè)位數(shù)運(yùn)算 2:十位數(shù)運(yùn)算);type=隨機(jī)字符時(shí),表示字符個(gè)數(shù) length: 1 # 驗(yàn)證碼字體 font: # 字體名稱 Dialog|DialogInput|Monospaced|Serif|SansSerif name: SansSerif # 字體樣式 0-普通|1-粗體|2-斜體 weight: 1 # 字體大小 size: 20 # 驗(yàn)證碼有效期(秒) expire-seconds: 120
以上就是SpringBoot3整合Hutool-captcha實(shí)現(xiàn)圖形驗(yàn)證碼的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot3 Hutool-captcha驗(yàn)證碼的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java8新特性stream和parallelStream區(qū)別
這篇文章主要介紹了Java8新特性stream和parallelStream區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11FastJson踩坑:@JsonField在反序列化時(shí)失效的解決
這篇文章主要介紹了FastJson踩坑:@JsonField在反序列化時(shí)失效的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06深入解析Jdk8中Stream流的使用讓你脫離for循環(huán)
這篇文章主要介紹了Jdk8中Stream流的使用,讓你脫離for循環(huán),本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02spring boot空屬性賦值問(wèn)題與aspect日志實(shí)現(xiàn)方法
這篇文章主要介紹了spring boot空屬性賦值問(wèn)題與aspect日志實(shí)現(xiàn)方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08restTemplate未設(shè)置連接數(shù)導(dǎo)致服務(wù)雪崩問(wèn)題以及解決
面對(duì)線上問(wèn)題,仔細(xì)分析原因,及時(shí)調(diào)整配置,能有效解決問(wèn)題,本文詳細(xì)描述了線上遇到流量突增引發(fā)的問(wèn)題,通過(guò)查看代碼和連接池信息,分析出問(wèn)題的原因是連接池滿了,連接池大小配置不足以應(yīng)對(duì)大并發(fā)流量,通過(guò)調(diào)整連接池大小配置2024-10-10SpringWebMVC的常用注解及應(yīng)用分層架構(gòu)詳解
這篇文章主要介紹了SpringWebMVC的常用注解及應(yīng)用分層架構(gòu),SpringWebMVC是基于ServletAPI構(gòu)建的原始Web框架,從?開(kāi)始就包含在Spring框架中,感興趣的朋友可以參考下2024-05-05SpringBoot集成MQTT實(shí)現(xiàn)交互服務(wù)通信
MQTT非常適用于物聯(lián)網(wǎng)領(lǐng)域,本文主要介紹了SpringBoot集成MQTT實(shí)現(xiàn)交互服務(wù)通信,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-08-08