在Java中創建一個驗證碼工具類,可以通過以下代碼實現。該工具類支持生成包含字母和數字的隨機驗證碼圖片,并添加干擾線和噪點以提高安全性。以下是詳細實現:
完整代碼實現
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Random;
import java.util.Base64;/*** 驗證碼生成工具類*/
public class CaptchaUtils {// 默認參數配置private static final int DEFAULT_WIDTH = 120; // 默認圖片寬度private static final int DEFAULT_HEIGHT = 40; // 默認圖片高度private static final int DEFAULT_CODE_LENGTH = 4; // 默認驗證碼長度private static final int DEFAULT_LINE_COUNT = 5; // 默認干擾線數量private static final int DEFAULT_NOISE_COUNT = 30; // 默認噪點數量// 可選字符集(排除易混淆字符)private static final String CHAR_SET = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789";/*** 生成驗證碼圖片和對應字符串* @return CaptchaResult 包含驗證碼圖片的Base64字符串和驗證碼值*/public static CaptchaResult generateCaptcha() {return generateCaptcha(DEFAULT_CODE_LENGTH, DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_LINE_COUNT, DEFAULT_NOISE_COUNT);}/*** 自定義參數的驗證碼生成方法*/public static CaptchaResult generateCaptcha(int codeLength, int width, int height, int lineCount, int noiseCount) {// 1. 生成隨機驗證碼字符串String code = generateRandomCode(codeLength);// 2. 創建圖片對象BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics2D g = image.createGraphics();// 3. 繪制背景色g.setColor(Color.WHITE);g.fillRect(0, 0, width, height);// 4. 繪制干擾線drawInterferenceLines(g, width, height, lineCount);// 5. 繪制驗證碼字符drawCode(g, code, width, height);// 6. 添加噪點addNoise(image, width, height, noiseCount);// 7. 釋放資源g.dispose();// 8. 轉換為Base64字符串String base64Image = convertImageToBase64(image);return new CaptchaResult(code, base64Image);}// 生成隨機驗證碼字符串private static String generateRandomCode(int length) {Random random = new Random();StringBuilder sb = new StringBuilder();for (int i = 0; i < length; i++) {int index = random.nextInt(CHAR_SET.length());sb.append(CHAR_SET.charAt(index));}return sb.toString();}// 繪制干擾線private static void drawInterferenceLines(Graphics2D g, int width, int height, int lineCount) {Random random = new Random();for (int i = 0; i < lineCount; i++) {int x1 = random.nextInt(width);int y1 = random.nextInt(height);int x2 = random.nextInt(width);int y2 = random.nextInt(height);g.setColor(getRandomColor());g.drawLine(x1, y1, x2, y2);}}// 繪制驗證碼字符private static void drawCode(Graphics2D g, String code, int width, int height) {Random random = new Random();g.setFont(new Font("Arial", Font.BOLD, 30));for (int i = 0; i < code.length(); i++) {// 字符顏色隨機g.setColor(getRandomColor());// 字符位置偏移int x = (width / code.length()) * i + 10;int y = height - 10;// 添加隨機旋轉double theta = Math.toRadians(random.nextInt(30) - 15); // -15°~15°g.rotate(theta, x, y);g.drawString(String.valueOf(code.charAt(i)), x, y);g.rotate(-theta, x, y); // 恢復角度}}// 添加噪點private static void addNoise(BufferedImage image, int width, int height, int noiseCount) {Random random = new Random();for (int i = 0; i < noiseCount; i++) {int x = random.nextInt(width);int y = random.nextInt(height);image.setRGB(x, y, getRandomColor().getRGB());}}// 生成隨機顏色(避免淺色)private static Color getRandomColor() {Random random = new Random();return new Color(random.nextInt(180), random.nextInt(180), random.nextInt(180));}// 將圖片轉為Base64字符串private static String convertImageToBase64(BufferedImage image) {try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {ImageIO.write(image, "JPEG", bos);byte[] bytes = bos.toByteArray();return "data:image/jpeg;base64," + Base64.getEncoder().encodeToString(bytes);} catch (IOException e) {throw new RuntimeException("生成驗證碼失敗", e);}}/*** 驗證碼結果封裝類*/public static class CaptchaResult {private final String code; // 驗證碼值private final String base64Image; // Base64格式圖片public CaptchaResult(String code, String base64Image) {this.code = code;this.base64Image = base64Image;}public String getCode() {return code;}public String getBase64Image() {return base64Image;}}// 測試public static void main(String[] args) {CaptchaResult result = CaptchaUtils.generateCaptcha();System.out.println("驗證碼值: " + result.getCode());System.out.println("Base64圖片:\n" + result.getBase64Image());}
}
核心功能說明
-
生成隨機字符串
- 使用預定義的字符集(排除易混淆字符如
0/O
、1/I
等)。 - 通過
Random
生成指定位數的驗證碼。
- 使用預定義的字符集(排除易混淆字符如
-
創建驗證碼圖片
- 使用
BufferedImage
創建畫布。 - 設置背景色為白色,并繪制干擾線和噪點。
- 使用
-
干擾元素設計
- 干擾線:隨機位置和顏色。
- 噪點:隨機位置的點狀干擾。
- 字符旋轉:每個字符隨機旋轉-15°~15°。
-
Base64編碼輸出
- 將生成的圖片轉為Base64字符串,便于Web前端直接顯示。
使用示例
// 生成默認驗證碼(4位,120x40像素)
CaptchaUtils.CaptchaResult result = CaptchaUtils.generateCaptcha();// 自定義參數生成驗證碼(6位,200x60像素,10條干擾線,50個噪點)
CaptchaUtils.CaptchaResult customResult = CaptchaUtils.generateCaptcha(6, 200, 60, 10, 50);// 獲取驗證碼值和圖片
String code = result.getCode();
String base64Image = result.getBase64Image();
優化點
-
安全性增強
- 使用
SecureRandom
代替Random
(需導入java.security.SecureRandom
)。 - 添加字符扭曲或縮放效果(需擴展
drawCode
方法)。
- 使用
-
擴展性
- 支持自定義字符集、字體類型、顏色范圍等參數。
- 通過
Builder模式
提供更靈活的配置。
-
性能優化
- 緩存常用參數配置的驗證碼樣式。
- 使用線程安全的隨機數生成器。
適用場景
- Web應用登錄/注冊的驗證碼校驗。
- 防止機器人批量操作的接口防護。