基于SpringBoot和Hutool工具包實(shí)現(xiàn)驗(yàn)證碼的案例
驗(yàn)證碼案例
隨著安全性的要求越來越高,目前項目中很多都會使用驗(yàn)證碼,只要涉及到登錄,絕大多數(shù)都會有驗(yàn)證的要求,驗(yàn)證碼的形式也是多種多樣,更復(fù)雜的圖形驗(yàn)證碼和行為驗(yàn)證碼已經(jīng)成為了更流行的趨勢。
驗(yàn)證碼的實(shí)現(xiàn)方式很多,可以前端實(shí)現(xiàn),也可以后端實(shí)現(xiàn)。網(wǎng)上也有比較多的插件或者工具包可以使用,這里選擇使用 Hutool工具包 來實(shí)現(xiàn)一個簡單的驗(yàn)證碼案例。完整代碼見文章末尾。
1. 需求
最終實(shí)現(xiàn)的驗(yàn)證碼界面如下圖所示:
1. 頁面生成驗(yàn)證碼
2. 輸入驗(yàn)證碼,點(diǎn)擊提交,驗(yàn)證用戶輸入驗(yàn)證碼是否正確且是否超時,正確且未超時則進(jìn)行頁面跳轉(zhuǎn),錯誤或已超時則進(jìn)行提示,并更換驗(yàn)證碼
2. 準(zhǔn)備工作
創(chuàng)建SpringBoot項目,引入Spring-Web-MVC和Lombok的依賴包,前端界面會在后面提供.
3. 約定前后端交互接口
需求分析
后端需要提供兩個服務(wù):
- 生成驗(yàn)證碼,并返回驗(yàn)證碼.
- 校驗(yàn)驗(yàn)證碼是否正確.
接口定義
1)生成驗(yàn)證碼
請求:
請求URL:/captcha/get
響應(yīng):瀏覽器顯示圖片內(nèi)容
瀏覽器給服務(wù)器發(fā)送一個 /captcha/get 請求,服務(wù)器返回一個圖片,瀏覽器顯示在頁面上
2)校驗(yàn)驗(yàn)證碼是否正確
請求:
請求URL:/captcha/check 請求參數(shù):captcha=驗(yàn)證碼字符串
響應(yīng):
true or false 根據(jù)用戶輸入的驗(yàn)證碼,校驗(yàn)驗(yàn)證碼是否正確,并判斷驗(yàn)證碼是否超時
4. Hutool 工具介紹
Hutool官網(wǎng):https://hutool.cn/
Hutool參考文檔:https://hutool.cn/docs/#/
要使用Hutool工具包,需要在pom.xml文件中添加對應(yīng)的依賴,參考文檔中有詳細(xì)介紹:
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.16</version> </dependency>
在Hutolol參考文檔中找到圖形驗(yàn)證碼部分:
接下來可以就可以參考Hutool工具提供的方法,快速生成驗(yàn)證碼,里面的介紹非常清晰,很容易看懂。此處使用如下格式驗(yàn)證碼:
5. 實(shí)現(xiàn)驗(yàn)證碼
項目目錄結(jié)構(gòu)如下:
后端代碼
實(shí)現(xiàn)接口
import cn.hutool.captcha.CaptchaUtil; import cn.hutool.captcha.LineCaptcha; import cn.hxxy.captchademo.config.CaptchaProperties; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.io.IOException; import java.util.Date; @RestController @RequestMapping("/captcha") public class CaptchaController { @Autowired private CaptchaProperties captchaProp; @RequestMapping("/get") public void getCaptcha(HttpServletResponse response, HttpSession session) { //定義圖形驗(yàn)證碼的長和寬(配置默認(rèn)值) LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(captchaProp.getWidth(), captchaProp.getHeight()); //細(xì)節(jié)問題,不影響程序 //設(shè)置返回類型 response.setContentType("image/jpeg"); //靜止緩存 response.setHeader("Progma", "No-cache"); try { //圖形驗(yàn)證碼寫出,可以寫出到文件,也可以寫出到流 lineCaptcha.write(response.getOutputStream()); //同時將驗(yàn)證碼內(nèi)容和當(dāng)前時間戳存儲到Session中 //此處Session的鍵可以配置成常量 session.setAttribute(captchaProp.getSession().getKey(), lineCaptcha.getCode()); session.setAttribute(captchaProp.getSession().getDate(), new Date()); //關(guān)流 response.getOutputStream().close(); } catch (IOException e) { throw new RuntimeException(e); } } //驗(yàn)證碼生效時間限制 private static final long VALID_MILLIS_TIME = 60 * 1000; @RequestMapping("/check") public boolean checkCaptcha(String captcha, HttpSession session) { //保證傳過來的參數(shù)是合法的 if (StringUtils.hasLength(captcha)) { //根據(jù)配置的默認(rèn)session信息獲取key和date String key = (String) session.getAttribute(captchaProp.getSession().getKey()); Date date = (Date) session.getAttribute(captchaProp.getSession().getDate()); //1.驗(yàn)證碼正確(不區(qū)分大小寫) 2.驗(yàn)證碼還未失效 return key.equalsIgnoreCase(captcha) && System.currentTimeMillis() - date.getTime() < VALID_MILLIS_TIME; } return false; } }
代碼解析:
通過@Autowired注解注入了一個CaptchaProperties對象,這個對象是用來配置圖形驗(yàn)證碼的屬性的。使用這種方式是因?yàn)榇a中的有些屬性可能會在別處使用,且它們都是固定的,例如圖形驗(yàn)證碼的長和寬,Session的字段名等。將這些屬性封裝在一個對象中,并通過讀取配置文件的方式綁定屬性值。
在@RequestMapping注解的getCaptcha方法中,使用Hutool包的CaptchaUtil.createLineCaptcha方法創(chuàng)建了一個圖形驗(yàn)證碼對象lineCaptcha,其大小由配置文件中的captchaProp.getWidth()和captchaProp.getHeight()決定。然后,將驗(yàn)證碼內(nèi)容和當(dāng)前時間戳存儲到HttpSession中,以便后續(xù)校驗(yàn)驗(yàn)證碼的時候使用。最后,將圖形驗(yàn)證碼寫出到HttpServletResponse的輸出流中,以返回給前端頁面顯示。
在@RequestMapping注解的checkCaptcha方法中,首先判斷傳入的驗(yàn)證碼參數(shù)是否合法。如果合法,則從HttpSession中獲取存儲的驗(yàn)證碼內(nèi)容和時間戳信息,并進(jìn)行比較。如果驗(yàn)證碼正確且未過期,則返回true,否則返回false。
CaptchaProperties類的實(shí)現(xiàn)和配置文件(.yml)信息如下
import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @Data @Configuration @ConfigurationProperties(prefix = "captcha") public class CaptchaProperties { private Integer width; private Integer height; private Session session; //使用自定義的Session類 @Data public static class Session { private String key; private String date; } }
spring: application: name: captcha-demo captcha: width: 200 height: 100 session: key: CAPTCHA_SESSION_KEY date: CAPTCHA_SESSION_DATE
此處還沒有前端代碼,但是已經(jīng)可以先測試了,通常寫好一個接口就可以測試一下。
啟動項目,再訪問 http://127.0.0.1:8080/captcha/get 顯示驗(yàn)證碼圖片如下:
通過 Fiddler 進(jìn)行抓包,HTTP請求和響應(yīng)數(shù)據(jù)如下,圖片就在響應(yīng)的body部分:
前端代碼
注意前端代碼要放在resources的static目錄下
index.html(重點(diǎn)關(guān)注script標(biāo)簽內(nèi)的代碼):
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>驗(yàn)證碼</title> <style> #inputCaptcha { height: 30px; vertical-align: middle; } #verificationCodeImg { vertical-align: middle; } #checkCaptcha { height: 40px; width: 100px; } </style> </head> <body> <h1>輸入驗(yàn)證碼</h1> <div id="confirm"> <input type="text" name="inputCaptcha" id="inputCaptcha"> <img id="verificationCodeImg" src="/captcha/get" style="cursor: pointer;" title="看不清?換一張"/> <input type="button" value="提交" id="checkCaptcha"> </div> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script> <script> //點(diǎn)擊圖片,切換驗(yàn)證碼 $("#verificationCodeImg").click(function () { //$(this).hide().attr('src', '/captcha/get?dt=' + new Date().getTime()).fadeIn(); //使用attr()方法修改src屬性值,獲取一個新的驗(yàn)證碼圖片,后面添加一個時間戳參數(shù)來保證每次請求的驗(yàn)證碼圖片都是不同的 $(this).attr('src', '/captcha/get?dt=' + new Date().getTime()); }); //點(diǎn)擊提交按鈕,進(jìn)行驗(yàn)證碼校驗(yàn) $("#checkCaptcha").click(function () { $.ajax({ url: "/captcha/check", type: "post", data: { captcha: $("#inputCaptcha").val() }, success: function (result) { if (result) { location.href = "success.html"; } else { alert("驗(yàn)證碼錯誤或已超時"); //驗(yàn)證碼錯誤,重新生成驗(yàn)證碼 $("#verificationCodeImg").attr('src', '/captcha/get?dt=' + new Date().getTime()); $("#inputCaptcha").val(""); } } }); }); </script> </body> </html>
JavaScript代碼中主要包含兩部分邏輯:
點(diǎn)擊圖片,切換驗(yàn)證碼: 當(dāng)id為"verificationCodeImg"的圖片被點(diǎn)擊時,會觸發(fā)click事件的回調(diào)函數(shù)?;卣{(diào)函數(shù)通過修改圖片的src屬性,向后端發(fā)送一個請求來獲取新的驗(yàn)證碼圖片,并使用當(dāng)前時間戳作為參數(shù),以確保每次請求的驗(yàn)證碼圖片都是不同的。最后,將獲取到的新圖片顯示出來。
點(diǎn)擊提交按鈕,進(jìn)行驗(yàn)證碼校驗(yàn): 當(dāng)id為"checkCaptcha"的按鈕被點(diǎn)擊時,會觸發(fā)click事件的回調(diào)函數(shù)?;卣{(diào)函數(shù)通過使用jQuery的ajax方法發(fā)送一個POST請求到"/captcha/check"接口,并傳遞了一個名為"captcha"的參數(shù),該參數(shù)的值為id為"inputCaptcha"的輸入框中用戶輸入的驗(yàn)證碼。
在請求成功后的回調(diào)函數(shù)中,會根據(jù)后端返回的結(jié)果(result)進(jìn)行處理。如果校驗(yàn)成功,則跳轉(zhuǎn)到"success.html"頁面;如果校驗(yàn)失敗,則彈出一個提示框顯示"驗(yàn)證碼錯誤或已超時",并重新生成新的驗(yàn)證碼圖片并清空輸入框中的驗(yàn)證碼。
success.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>驗(yàn)證成功頁</title> </head> <body> <h1>驗(yàn)證成功</h1> </body> </html>
6. 運(yùn)行測試
啟動項目,瀏覽器訪問 http://127.0.0.1:8080/index.html 或 http://localhost:8080/index.html
輸入錯誤的驗(yàn)證碼:
提示正確,且驗(yàn)證碼能正確刷新,超時同樣會提示以上錯誤。且點(diǎn)擊驗(yàn)證碼圖片時,會重新生成驗(yàn)證碼。
驗(yàn)證成功,頁面正確跳轉(zhuǎn),測試完成。
以上就是基于SpringBoot和Hutool工具包實(shí)現(xiàn)驗(yàn)證碼的案例的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot Hutool驗(yàn)證碼的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
springboot基于docsify?實(shí)現(xiàn)隨身文檔
這篇文章主要介紹了springboot基于docsify實(shí)現(xiàn)隨身文檔的相關(guān)資料,需要的朋友可以參考下2022-09-09Java原生方法實(shí)現(xiàn) AES 算法示例
這篇文章主要介紹了Java原生方法實(shí)現(xiàn) AES 算法,結(jié)合實(shí)例形式分析了Java實(shí)現(xiàn)AES加密算法的相關(guān)操作技巧,需要的朋友可以參考下2019-03-03深入Spring Boot實(shí)現(xiàn)對Fat Jar jsp的支持
這篇文章主要介紹了深入Spring Boot實(shí)現(xiàn)對Fat Jar jsp的支持,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-06-06java中Executor,ExecutorService,ThreadPoolExecutor詳解
這篇文章主要介紹了java中Executor,ExecutorService,ThreadPoolExecutor詳解的相關(guān)資料,需要的朋友可以參考下2017-02-02java基于servlet編寫上傳下載功能 類似文件服務(wù)器
這篇文章主要為大家詳細(xì)介紹了java基于servlet編寫上傳下載功能,類似文件服務(wù)器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-07-07