导包
<!-- 谷歌验证码组件 -->
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
工具类
import static com.google.code.kaptcha.Constants.KAPTCHA_BORDER;
import static com.google.code.kaptcha.Constants.KAPTCHA_BORDER_COLOR;
import static com.google.code.kaptcha.Constants.KAPTCHA_IMAGE_HEIGHT;
import static com.google.code.kaptcha.Constants.KAPTCHA_IMAGE_WIDTH;
import static com.google.code.kaptcha.Constants.KAPTCHA_NOISE_COLOR;
import static com.google.code.kaptcha.Constants.KAPTCHA_NOISE_IMPL;
import static com.google.code.kaptcha.Constants.KAPTCHA_OBSCURIFICATOR_IMPL;
import static com.google.code.kaptcha.Constants.KAPTCHA_SESSION_CONFIG_KEY;
import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH;
import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_CHAR_SPACE;
import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR;
import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_FONT_NAMES;
import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE;
import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_IMPL;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import javax.imageio.ImageIO;
import com.google.code.kaptcha.Producer;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.text.impl.DefaultTextCreator;
import com.google.code.kaptcha.util.Config;
/**
* 验证码操作相关工具类
*
* @author ycs
*/
public class YcsCaptchaCodeUtils extends DefaultTextCreator {
/**
* 数学验证码计算式数据来源
*/
private static final String[] NUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");
/**
* 数学验证码计算式对应索引
*/
public static final String MATH_KEY = "key";
/**
* 数据验证码计算式结果对应索引
*/
public static final String MATH_VAL = "val";
public static final String SPLIT = "@";
public static final String EXTENSION = "jpg";
private static final Producer charProducer = CaptchaConfig.getCharProducer();
private static final Producer mathProducer = CaptchaConfig.getMathProducer();
/**
* 获取字符验证码文本
*
* @return
*/
public static String createCharText() {
return charProducer.createText();
}
/**
* 获取字符验证码图片
*
* @param charText 字符验证码文本
* @return
*/
public static BufferedImage createCharImage(String charText) {
return charProducer.createImage(charText);
}
/**
* 获取数学验证码计算式和计算结果
* <p>
* 计算式 = result.get(YcsCaptchaCodeUtils.MATH_KEY)
* <p>
* 计算值 = result.get(YcsCaptchaCodeUtils.MATH_VAL)
*
* @return result
*/
public static Map<String, String> createMathText() {
String text = mathProducer.createText();
String key = text.substring(0, text.lastIndexOf(SPLIT));
String val = text.substring(text.lastIndexOf(SPLIT) + 1);
Map<String, String> result = new HashMap<>();
result.put(MATH_KEY, key);
result.put(MATH_VAL, val);
return result;
}
/**
* 获取数学验证码图片
*
* @param mathText 数学验证码计算式
* @param outputStream 图片输出流
* @return
*/
public static void createMathImage(String mathText, OutputStream outputStream) {
BufferedImage mathImage = mathProducer.createImage(mathText);
try {
ImageIO.write(mathImage, EXTENSION, outputStream);
} catch (IOException e) {
throw new RuntimeException("获取数学验证码图片失败!\n" + e);
}
}
@Override
public String getText() {
int result = 0;
Random random = new Random();
int x = random.nextInt(10);
int y = random.nextInt(10);
StringBuilder suChinese = new StringBuilder();
int randomOperands = (int) Math.round(Math.random() * 2);
if (randomOperands == 0) {
result = x * y;
suChinese.append(NUMBERS[x]);
suChinese.append(" * ");
suChinese.append(NUMBERS[y]);
} else if (randomOperands == 1) {
if (!(x == 0) && y % x == 0) {
result = y / x;
suChinese.append(NUMBERS[y]);
suChinese.append(" / ");
suChinese.append(NUMBERS[x]);
} else {
result = x + y;
suChinese.append(NUMBERS[x]);
suChinese.append(" + ");
suChinese.append(NUMBERS[y]);
}
} else if (randomOperands == 2) {
if (x >= y) {
result = x - y;
suChinese.append(NUMBERS[x]);
suChinese.append(" - ");
suChinese.append(NUMBERS[y]);
} else {
result = y - x;
suChinese.append(NUMBERS[y]);
suChinese.append(" - ");
suChinese.append(NUMBERS[x]);
}
} else {
result = x + y;
suChinese.append(NUMBERS[x]);
suChinese.append(" + ");
suChinese.append(NUMBERS[y]);
}
suChinese.append(" = ?").append(SPLIT).append(result);
return suChinese.toString();
}
}
class CaptchaConfig {
/**
* 字符验证码
*
* @return
*/
static DefaultKaptcha getCharProducer() {
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
// 是否有边框 默认为yes-有
properties.setProperty(KAPTCHA_BORDER, "no");
// 验证码文本字符颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
// 验证码图片宽度 默认为200
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
// 验证码图片高度 默认为50
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
// 验证码文本字符大小 默认为40
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
// KAPTCHA_SESSION_KEY
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
// 验证码文本字符长度 默认为5
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
/**
* 数学表达式验证码,使用 @ 分隔计算式和结果, 如 1 + 2 = @3
*
* @return
*/
static DefaultKaptcha getMathProducer() {
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
// 是否有边框 默认为yes-有
properties.setProperty(KAPTCHA_BORDER, "no");
// 边框颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
// 验证码文本字符颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
// 验证码图片宽度 默认为200
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
// 验证码图片高度 默认为50
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
// 验证码文本字符大小 默认为40
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");
// KAPTCHA_SESSION_KEY
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
// 验证码文本生成器
properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.ycsyxt.YcsCaptchaCodeUtils");
// 验证码文本字符间距 默认为2
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
// 验证码文本字符长度 默认为5
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
// 验证码噪点颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
// 干扰实现类
properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}
测试
/**
* @author ycs
*/
public class SelfTest {
private File desktopDir;
/**
* 系统桌面路径
*/
private String desktopPath;
@Before
public void desktopDirTest() {
desktopDir = FileSystemView.getFileSystemView().getHomeDirectory();
desktopPath = desktopDir.getAbsolutePath();
}
@Test
public void captchaCodeUtilsTest() {
String charText = YcsCaptchaCodeUtils.createCharText();
BufferedImage charImage = YcsCaptchaCodeUtils.createCharImage(charText);
try (OutputStream outputStream = new FileOutputStream(desktopPath + "/charText.jpg")) {
ImageIO.write(charImage, "jpg", outputStream);
} catch (Exception e) {
throw new RuntimeException(e);
}
System.out.println(charText);
Map<String, String> result = YcsCaptchaCodeUtils.createMathText();
try (OutputStream outputStream = new FileOutputStream(desktopPath + "/imageText.jpg")) {
YcsCaptchaCodeUtils.createMathImage(result.get(YcsCaptchaCodeUtils.MATH_KEY), outputStream);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}