title: Java 生成验证码 Captcha date: 2022-03-19 10:27:25 categories: 学习&开发&实现 tag:
方法效率较低,推荐使用缓存,重复使用验证码
// 验证码宽度
private static final Integer CAPTCHA_WIDTH = 150;
// 验证码高度
private static final Integer CAPTCHA_HEIGHT = 40;
// 验证码最大旋转角度(不推荐修改)
private static final Integer CAPTCHA_CHAR_ROTATE = 5;
// 干扰线数量
private static final Integer CAPTCHA_LINE_NUM = 5;
// 验证码数量
private static final Integer CAPTCHA_CHAR_NUM = 4;
// 验证码的保存格式
private static final String CAPTCHA_CONTENT_TYPE = "PNG";
public static String createCaptcha(OutputStream outputStream) throws PortableException {
BufferedImage image = new BufferedImage(CAPTCHA_WIDTH, CAPTCHA_HEIGHT, BufferedImage.TYPE_INT_BGR);
Graphics2D g = (Graphics2D) image.getGraphics();
g.fillRect(0, 0, CAPTCHA_WIDTH, CAPTCHA_HEIGHT);
for (int i = 0; i < CAPTCHA_LINE_NUM; i++) {
drawRandomLine(g);
}
for (int i = 0; i < CAPTCHA_LINE_NUM; i++) {
drawLeftToRightLine(g);
}
StringBuilder ans = new StringBuilder();
for (int i = 0; i < CAPTCHA_CHAR_NUM; i++) {
ans.append(drawString(g, i + 1));
}
try {
ImageIO.write(image, CAPTCHA_CONTENT_TYPE, outputStream);
} catch (IOException e) {
throw PortableException.of("B-01-002");
}
return ans.toString();
}
private static void drawRandomLine(Graphics2D g) {
int xs = RANDOM.nextInt(CAPTCHA_WIDTH);
int xe = RANDOM.nextInt(CAPTCHA_WIDTH);
int ys = RANDOM.nextInt(CAPTCHA_HEIGHT);
int ye = RANDOM.nextInt(CAPTCHA_HEIGHT);
g.setFont(ARIAL_FONT);
g.setColor(getRandomColor());
g.drawLine(xs, ys, xe, ye);
}
private static void drawLeftToRightLine(Graphics2D g) {
int xs = RANDOM.nextInt(CAPTCHA_WIDTH / 2);
int xe = CAPTCHA_WIDTH / 2 + RANDOM.nextInt(CAPTCHA_WIDTH / 2);
int ys = RANDOM.nextInt(CAPTCHA_HEIGHT / 2);
int ye = CAPTCHA_HEIGHT / 2 + RANDOM.nextInt(CAPTCHA_HEIGHT / 2);
g.setFont(ARIAL_FONT);
g.setColor(getRandomColor());
g.drawLine(xs, ys, xe, ye);
}
private static String drawString(Graphics2D g, Integer num) {
// 保证左侧和右侧不要贴边,总共留出一个字符的空间
int baseX = (int) (CAPTCHA_WIDTH * 1.0 / (ImageUtils.CAPTCHA_CHAR_NUM + 1) * num);
AffineTransform old = g.getTransform();
String c = getRandomChar();
g.setFont(ARIAL_FONT);
g.setColor(getRandomColor());
g.rotate(Math.toRadians(RANDOM.nextInt(CAPTCHA_CHAR_ROTATE * 2) - CAPTCHA_CHAR_ROTATE));
g.drawString(c, baseX, CAPTCHA_HEIGHT / 3 * 2);
g.setTransform(old);
return c;
}
private static Color getRandomColor() {
int upper = 128;
int lower = 0;
int r = lower + RANDOM.nextInt(upper);
int g = lower + RANDOM.nextInt(upper);
int b = lower + RANDOM.nextInt(upper);
return new Color(r, g, b);
}
private static String getRandomChar() {
return String.valueOf(CAPTCHA_CHAR.charAt(RANDOM.nextInt(CAPTCHA_CHAR.length())));
}