基于Java實現(xiàn)圖形驗證碼工具類
更新時間:2024年11月20日 09:39:34 作者:一線大碼
這篇文章主要為大家詳細介紹了如何基于Java實現(xiàn)圖形驗證碼工具類,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
工具類:
package com.example.demo.util;
import lombok.extern.slf4j.Slf4j;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.security.SecureRandom;
/**
* 驗證碼工具類
*
* @author wangbo
* @since 2024/10/29
*/
@Slf4j
public class CaptchaGeneratorUtil {
private CaptchaGeneratorUtil() {
// ...
}
public static void main(String[] args) throws IOException {
// 生成4位隨機數(shù)字驗證碼
String text = generateRandomCode();
// 創(chuàng)建驗證碼圖片
BufferedImage image = createImage(text);
// 保存圖片到文件
ImageIO.write(image, "png", new File("captcha.png"));
}
private static final SecureRandom RANDOM = new SecureRandom();
/**
* 生成4位隨機數(shù)字字母驗證碼
*/
public static String generateRandomCode() {
StringBuilder code = new StringBuilder();
for (int i = 0; i < 4; i++) {
int i1 = RANDOM.nextInt(3);
if (i1 == 0) {
code.append((char) (RANDOM.nextInt(26) + 65));
} else if (i1 == 1) {
code.append((char) (RANDOM.nextInt(26) + 97));
} else {
code.append(RANDOM.nextInt(10));
}
}
log.info("生成的驗證碼文本 text = {}", code);
return code.toString();
}
/**
* 創(chuàng)建驗證碼圖片
*/
public static BufferedImage createImage(String text) {
log.info("待生成驗證碼圖片的文本 text = {}", text);
int width = 75;
int height = 25;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 使用Graphics2D以獲得更好的圖形控制
Graphics2D g2d = image.createGraphics();
try {
// 設(shè)置背景顏色
g2d.setColor(new Color(0xDCDCDC));
g2d.fillRect(0, 0, width, height);
// 設(shè)置字體和顏色
g2d.setFont(new Font("Arial", Font.BOLD, 20));
g2d.setColor(new Color(0x004000));
// 確保文本不會超出圖像邊界
FontMetrics fm = g2d.getFontMetrics();
int textWidth = fm.stringWidth(text);
// 居中文本
int x = (width - textWidth) / 2;
// 居中文本(基線對齊)
int y = (height - fm.getHeight()) / 2 + fm.getAscent();
g2d.drawString(text, x, y);
// 添加噪聲線
for (int i = 0; i < 5; i++) {
g2d.setColor(new Color(RANDOM.nextInt(255), RANDOM.nextInt(255), RANDOM.nextInt(255)));
g2d.drawLine(RANDOM.nextInt(width), RANDOM.nextInt(height), RANDOM.nextInt(width), RANDOM.nextInt(height));
}
// 設(shè)置渲染提示以提高圖像質(zhì)量(可選)
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
} finally {
// 確保在try塊之后釋放Graphics2D資源
g2d.dispose();
}
return image;
}
private static final String CAPTCHA_PREFIX = "captcha:";
public static String generateCaptchaRedisKey(String key) {
return CAPTCHA_PREFIX + key;
}
}
生成圖片驗證碼接口(該接口無需權(quán)限校驗):
/**
* 生成圖片驗證碼
*
* @param key UUID字符串
*/
@GetMapping("/captcha/generator/{key}")
public void captchaGenerator(@PathVariable("key") String key, HttpServletResponse response) throws BaseException {
userService.captchaGenerator(key, response);
}
public void captchaGenerator(String key, HttpServletResponse response) throws BaseException {
//查看key的驗證碼是否已存在
String captchaRedisKey = CaptchaGeneratorUtil.generateCaptchaRedisKey(key);
boolean hasKey = Boolean.TRUE.equals(redisTemplate.hasKey(captchaRedisKey));
if (hasKey) {
throw new BaseException(ErrorCode.USER_KEY_REPETITION);
}
String captcha = CaptchaGeneratorUtil.generateRandomCode();
BufferedImage image = CaptchaGeneratorUtil.createImage(captcha);
//設(shè)置驗證碼,有效期1分鐘
redisTemplate.opsForValue().set(captchaRedisKey, captcha, 60L, TimeUnit.SECONDS);
response.setContentType("image/jpeg");
try (ServletOutputStream out = response.getOutputStream()) {
ImageIO.write(image, "JPEG", out);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
登錄接口或者其他涉及驗證碼的接口進行驗證碼校驗:
//校驗驗證碼
String key = loginPage.getKey();
String captcha = loginPage.getCaptcha();
if (StringUtils.isNullOrEmpty(key) || StringUtils.isNullOrEmpty(captcha)) {
throw new BaseException(ErrorCode.USER_KEY_OR_CAPTCHA_NOT_FOUND);
}
String captchaRedisKey = CaptchaGeneratorUtil.generateCaptchaRedisKey(key);
String redisCaptcha = redisTemplate.opsForValue().get(captchaRedisKey);
if (StringUtils.isNullOrEmpty(redisCaptcha) || !captcha.equalsIgnoreCase(redisCaptcha)) {
throw new BaseException(ErrorCode.USER_CAPTCHA_ERROR);
} else {
//刪除驗證碼緩存
redisTemplate.delete(captchaRedisKey);
}
到此這篇關(guān)于基于Java實現(xiàn)圖形驗證碼工具類的文章就介紹到這了,更多相關(guān)Java圖形驗證碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Springboot攔截器如何獲取@RequestBody參數(shù)
這篇文章主要介紹了Springboot攔截器如何獲取@RequestBody參數(shù)的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06
Springboot使用JustAuth實現(xiàn)各種第三方登陸
本文主要介紹了Springboot使用JustAuth實現(xiàn)各種第三方登陸,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
使用Java?Executors創(chuàng)建線程池的9種方法
文章主要介紹了?Java?中Executors類創(chuàng)建線程池的?9?種方法,每種方法都詳細闡述了實現(xiàn)原理、源代碼分析、參數(shù)解釋、實現(xiàn)過程、特性和使用場景,感興趣的小伙伴跟著小編一起來看看吧2024-11-11
由@NotNull注解引出的關(guān)于Java空指針的控制
這是一些很容易學(xué)會的簡單技術(shù),但是對于代碼質(zhì)量和健壯性來說確實很重要。以我的經(jīng)驗,僅是第一個小技巧就已經(jīng)對改進代碼質(zhì)量具有很大的作用了2016-09-09
統(tǒng)一建模語言_動力節(jié)點Java學(xué)院整理
這篇文章主要介紹了統(tǒng)一建模語言的相關(guān)知識,非常不錯,具有參考借鑒價值,需要的的朋友參考下吧2017-06-06

