java运算验证码的做法
前面写了生成文字验证码,现在来做一个稍微高级点的运算验证码。也就是通过运算得到结果作为验证码
直接上代码:
/**
* 运算验证码
*
* @author lc
* 2020-01-20
*/
@Controller
@RequestMapping("/kaptcha")
public class CalculatorKaptcha {
private static StringBuilder result = new StringBuilder();
@RequestMapping("/generatekaptcha")
public void outputKaptcha(HttpServletResponse response) {
Map<String, Object> operationMap = new HashMap<>();
operationMap.clear();
operationMap = generatorOperationVerificationCode();
//图片
BufferedImage bufferedImage2 = (BufferedImage) operationMap.get("verificationCodeImage");
//生成文字验证码
String text = (String) operationMap.get("verificationCode");
System.out.println(text);
/**
* 这里用于缓存验证码结果,放缓存类或者redis都可以
* 这里忽略
*/
response.setHeader("Cache-Control", "no-store, no-cache");
response.setContentType("image/jpeg");
ServletOutputStream sos = null;
try {
sos = response.getOutputStream();
ImageIO.write(bufferedImage2, "jpg", sos);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != sos) {
try {
sos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 生成运算验证码
*
* @return 运算验证码
*/
public Map<String, Object> generatorOperationVerificationCode() {
// 验证码图片边框宽度
final int WIDTH = 185;
// 验证码图片边框高度
final int HEIGHT = 50;
// 验证码字体高度
int FONT_HEIGHT = HEIGHT - 12;
// 验证码干扰线条数
int INTERFERENCE_LINE = 4;
// 字体大小
int FONT_SIZE = 30;
Map<String, Object> verificationCodeMap = null;
Random ran = new Random();
// 生成透明rgb图片
BufferedImage bufferedImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics graphics = bufferedImage.getGraphics();
/**
* 1.画验证码底部颜色和大小,和边框颜色设置
*/
Color color = graphics.getColor();
// 图片全部填充填充黑色
graphics.setColor(Color.BLACK);
graphics.fillRect(0, 0, WIDTH, HEIGHT);
// 图片填充白色;组成黑色边框的白色图片(从1,1的位置到x轴WIDTH - 2,y轴HEIGHT - 2,
//都填充为白色,那么只剩边框是黑的了)
graphics.setColor(Color.white);
graphics.fillRect(1, 1, WIDTH - 2, HEIGHT - 2);
/**
* 2.验证码字符串
* 获取生成的表达式完整的:27 * 20 = ?@540
* 再切割
*/
String text = getText();
System.out.println(text);
// 运算表达式
String operationExpression = text.substring(0, text.lastIndexOf("@") - 1);
// 计算结果
String result = text.substring(text.lastIndexOf("@") + 1, text.length());
/**
* 3.设置字体大小,30-45之间随机变化
* 字体颜色:随机颜色
*/
int size = (ran.nextInt(15) + FONT_SIZE);
// 设置画笔字体
Font font = new Font(null, Font.ITALIC, size);
graphics.setFont(font);
// 根据系统时间创建随机数对象
graphics.setColor(getRandomColor());
// 根据画笔颜色绘制字符
graphics.drawString(operationExpression, 5, FONT_HEIGHT);
/**
* 4. 绘制干扰线
*/
for (int i = 0; i < INTERFERENCE_LINE; i++) {
// 随机生成rgb颜色值,并设置画笔颜色
graphics.setColor(getRandomColor());
// 设置画笔字体
Font interference_line_font = new Font("微软雅黑", Font.PLAIN, FONT_HEIGHT);
graphics.setFont(interference_line_font);
//设置干扰线的起始
graphics.drawLine(ran.nextInt(WIDTH), ran.nextInt(HEIGHT),
ran.nextInt(WIDTH), ran.nextInt(HEIGHT));
}
// 恢复画笔颜色
graphics.setColor(color);
verificationCodeMap = new HashMap<>();
verificationCodeMap.put("verificationCodeImage", bufferedImage);
verificationCodeMap.put("verificationCode", result);
return verificationCodeMap;
}
//获取随机颜色
private Color getRandomColor() {
Random ran = new Random();
Color color = new Color(ran.nextInt(256),
ran.nextInt(256), ran.nextInt(256));
return color;
}
/**
* 获取运算验证码
*
* @return 运算验证码
*/
public static String getText() {
Random random = new Random();
int x = 0;
x = random.nextInt(31);
int y = 0;
y = random.nextInt(31);
int operationalRules = random.nextInt(4);
result = new StringBuilder();
switch (operationalRules) {
case 0:
add(x, y);
break;
case 1:
subtract(x, y);
break;
case 2:
multiply(x, y);
break;
case 3:
divide(x, y);
break;
}
return result.toString();
}
/**
* 加法运算
*
* @param x 变量x
* @param y 变量y
*/
private static void add(int x, int y) {
result.append(x);
result.append(" + ");
result.append(y);
result.append(" = ?@");
result.append(x + y);
}
/**
* 减法运算
*
* @param x 变量x
* @param y 变量y
*/
private static void subtract(int x, int y) {
//取两个数字中最大的
int max = Math.max(x, y);
//取两个数字中最小的
int min = Math.min(x, y);
result.append(max);
result.append(" - ");
result.append(min);
result.append(" = ?@");
result.append(max - min);
}
/**
* 乘法运算
*
* @param x 变量x
* @param y 变量y
*/
private static void multiply(int x, int y) {
int value = x * y;
result.append(x);
result.append(value > 1000 ? " + " : " * ");
result.append(y);
result.append(" = ?@");
result.append(value > 1000 ? x + y : x * y);
}
/**
* 除发运算
* @param x 变量x
* @param y 变量y
*/
private static void divide(int x, int y) {
int max = Math.max(x, y);
int min = Math.min(x, y);
if (min == 0) {
multiply(max, min);
//可以整除才有除法(以取余数是否为0作判断是否能整除)
} else if (max % min == 0) {
result.append(max);
result.append("÷");
result.append(min);
result.append(" = ?@");
result.append(max / min);
} else {
//不能整除就做减法
subtract(max, min);
}
}
}