SpringBoot后端驗(yàn)證碼的實(shí)現(xiàn)示例
一、簡(jiǎn)介
為了防止網(wǎng)站的用戶被通過(guò)密碼典爆破。引入驗(yàn)證碼的功能是十分有必要的。而前端的驗(yàn)證碼又僅僅是只防君子不防小人。通過(guò)burpsuit等工具很容易就會(huì)被繞過(guò)。所以后端實(shí)現(xiàn)的驗(yàn)證碼才是對(duì)用戶信息安全的一大重要保障。

實(shí)現(xiàn)思路:
1.引入圖形生成的依賴
2.生成隨機(jī)4字符,并制作成圖片
3.對(duì)圖片進(jìn)行Base64形式數(shù)據(jù)進(jìn)行傳輸
4.前端顯示
二、引入依賴
<!-- 驗(yàn)證碼模塊-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>三、驗(yàn)證碼生成工具類
public class CaptchaUtil {
private static final int WIDTH = 200;
private static final int HEIGHT = 75;
private static final int FONT_SIZE = 36;
private static final String DEFAULT_FONT = "Arial";
/**
* 生成驗(yàn)證碼圖像.
*
* @param captchaText 驗(yàn)證碼原始文本
* @return Base64編碼的圖像字符串
*/
public static String generateCaptchaImage(String captchaText) {
if (captchaText == null || captchaText.isEmpty()) {
throw new IllegalArgumentException("Captcha text cannot be null or empty.");
}
// 創(chuàng)建圖像和圖形上下文
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D) image.getGraphics();
// 設(shè)置背景顏色
g.setColor(Color.WHITE);
g.fillRect(0, 0, WIDTH, HEIGHT);
// 繪制驗(yàn)證碼文本
g.setFont(new Font(DEFAULT_FONT, Font.BOLD, FONT_SIZE));
g.setColor(getRandomColor());
g.drawString(captchaText, 45, 50);
// 添加隨機(jī)線條作為干擾
addNoiseLines(g);
// 關(guān)閉圖形上下文
g.dispose();
// 將圖像轉(zhuǎn)換為Base64編碼的字符串
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
ImageIO.write(image, "png", baos);
return Base64.getEncoder().encodeToString(baos.toByteArray());
} catch (Exception e) {
throw new RuntimeException("Error generating captcha image", e);
}
}
private static void addNoiseLines(Graphics2D g) {
for (int i = 0; i < 5; i++) {
g.setColor(getRandomColor());
g.drawLine(
getRandomNumber(WIDTH),
getRandomNumber(HEIGHT),
getRandomNumber(WIDTH),
getRandomNumber(HEIGHT)
);
}
}
private static Color getRandomColor() {
return new Color((int) (Math.random() * 255),
(int) (Math.random() * 255),
(int) (Math.random() * 255));
}
private static int getRandomNumber(int bound) {
return (int) (Math.random() * bound);
}
}四、通過(guò)Http Session存放驗(yàn)證碼與驗(yàn)證
獲取(a-z A-Z 0-9)隨機(jī)四位的驗(yàn)證碼功能:
// 登陸時(shí)候獲取驗(yàn)證碼
@ApiOperation("獲取驗(yàn)證碼功能")
@GetMapping("/GetCaptcha")
public String GetCaptcha(HttpSession session) {
// 隨機(jī)生成四位驗(yàn)證碼原始數(shù)據(jù)
String allowedChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
String randomString = generateRandomString(allowedChars, 4);
System.out.println("captchaCode " + randomString);
// 將驗(yàn)證碼保存到session中
session.setAttribute("captcha", randomString); // 使用方法參數(shù)session
String ImageByBase64 = CaptchaUtil.generateCaptchaImage(randomString);
return ImageByBase64;
}用戶登陸時(shí)候校驗(yàn)驗(yàn)證碼功能:
// 實(shí)現(xiàn)登陸功能
@ApiOperation("用戶登陸功能")
@PostMapping("/login")
public Result Login(@RequestBody LoginDTO loginDTO, HttpSession session) { // 使用同一個(gè)HttpSession參數(shù)
String captcha = (String) session.getAttribute("captcha");
log.info("用戶調(diào)用login方法");
if (loginDTO.getCaptcha() == null || !loginDTO.getCaptcha().equalsIgnoreCase(captcha)) {
session.removeAttribute("captcha");
return Result.error("驗(yàn)證碼出錯(cuò)了噢!");
}
// 對(duì)密碼進(jìn)行md5加密
String encryptToMD5 = MD5Util.encryptToMD5(loginDTO.getPassword());
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(User::getAccount, loginDTO.getAccount())
.eq(User::getPassword, encryptToMD5);
User user = userService.getOne(lambdaQueryWrapper);
if (user == null) {
return Result.error("很抱歉,查不到此用戶");
}
user.setPassword("xxxxx");
return Result.success(user);
}五、前端顯示Base64格式的圖片
前端實(shí)現(xiàn)注冊(cè)的表單
<el-tab-pane label="登陸" name="first">
<el-form :model="loginForm" ref="loginFormRef" label-width="80px">
<el-form-item label="用戶名:">
<el-input v-model="loginForm.account"></el-input>
</el-form-item>
<el-form-item label="密碼:">
<el-input v-model="loginForm.password" show-password></el-input>
</el-form-item>
<el-form-item label="驗(yàn)證碼">
<el-input v-model="loginForm.captcha" style="width: 20%;"></el-input>
<img :src="captchaImageUrl" alt="驗(yàn)證碼" @click="refreshCaptcha" id="captchaImage">
</el-form-item>
</el-form>
</el-tab-pane>先設(shè)置為空
export default {
data() {
return {
captchaImageUrl: '', // 初始化為一個(gè)空字符串
}
},在點(diǎn)擊登陸按鈕后,執(zhí)行g(shù)etCaptcha函數(shù)并設(shè)置captchaImageUrl的回顯格式為Base64
fetchCaptcha() {
axios.get('/api/user/GetCaptcha')
.then(response => {
this.captchaImageUrl = 'data:image/png;base64,' + response.data;
})
.catch(error => {
console.error('獲取驗(yàn)證碼失敗:', error);
});
},最后進(jìn)行測(cè)試:

注意:實(shí)現(xiàn)完成驗(yàn)證碼功能后,需要注意用戶的操作。如果登陸失敗,刷新頁(yè)面,切換頁(yè)面。都需要重新更新驗(yàn)證碼!
到此這篇關(guān)于SpringBoot后端驗(yàn)證碼的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)SpringBoot后端驗(yàn)證碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot實(shí)現(xiàn)短信驗(yàn)證碼校驗(yàn)方法思路詳解
- SpringBoot 集成Kaptcha實(shí)現(xiàn)驗(yàn)證碼功能實(shí)例詳解
- SpringBoot實(shí)現(xiàn)前端驗(yàn)證碼圖片生成和校驗(yàn)
- Springboot實(shí)現(xiàn)驗(yàn)證碼登錄
- SpringBoot發(fā)送郵箱驗(yàn)證碼功能
- SpringBoot使用郵箱發(fā)送驗(yàn)證碼實(shí)現(xiàn)注冊(cè)功能
- springboot實(shí)現(xiàn)郵箱驗(yàn)證碼功能
- SpringBoot發(fā)送郵件功能 驗(yàn)證碼5分鐘過(guò)期
- SpringBoot登錄驗(yàn)證碼實(shí)現(xiàn)過(guò)程詳解
相關(guān)文章
Java調(diào)用C++動(dòng)態(tài)庫(kù)超詳細(xì)步驟講解(附源碼)
C語(yǔ)言因其高效和接近硬件的特性,時(shí)常會(huì)被用在性能要求較高或者需要直接操作硬件的場(chǎng)合,這篇文章主要介紹了Java調(diào)用C++動(dòng)態(tài)庫(kù)的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-04-04
解決springboot中配置過(guò)濾器以及可能出現(xiàn)的問(wèn)題
這篇文章主要介紹了解決springboot中配置過(guò)濾器以及可能出現(xiàn)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09
java實(shí)現(xiàn)入棧push和出棧pop過(guò)程
文章詳細(xì)介紹了棧的概念、特點(diǎn)以及如何使用數(shù)組和鏈表實(shí)現(xiàn)棧,通過(guò)入棧(push)和出棧(pop)操作,展示了棧的數(shù)據(jù)處理過(guò)程,并提供了具體的代碼實(shí)現(xiàn)2024-12-12
eclipse springboot工程打war包方法及再Tomcat中運(yùn)行的方法
這篇文章主要介紹了eclipse springboot工程打war包方法及再Tomcat中運(yùn)行的方法,本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08
從最基本的Java工程搭建SpringMVC+SpringDataJPA+Hibernate
本文會(huì)介紹從一個(gè)最基本的java工程,到Web工程,到集成Spring、SpringMVC、SpringDataJPA+Hibernate,本文介紹的非常詳細(xì),具有參考借鑒價(jià)值,感興趣的朋友一起學(xué)習(xí)吧2016-05-05
java 使用ConcurrentHashMap和計(jì)數(shù)器實(shí)現(xiàn)鎖
這篇文章主要介紹了java 使用ConcurrentHashMap和計(jì)數(shù)器實(shí)現(xiàn)鎖的相關(guān)資料,需要的朋友可以參考下2017-05-05
如何使用Java實(shí)現(xiàn)請(qǐng)求deepseek
這篇文章主要為大家詳細(xì)介紹了如何使用Java實(shí)現(xiàn)請(qǐng)求deepseek功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-02-02
詳解java中List中set方法和add方法的區(qū)別
本文主要介紹了詳解java中List中set方法和add方法的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08

