|
|
@@ -1,14 +1,8 @@
|
|
|
package com.uas.sso.util;
|
|
|
|
|
|
-import com.uas.sso.exception.VisibleError;
|
|
|
-import org.springframework.util.StringUtils;
|
|
|
-
|
|
|
-import java.awt.Color;
|
|
|
-import java.awt.Font;
|
|
|
-import java.awt.Graphics2D;
|
|
|
+import java.awt.*;
|
|
|
import java.awt.image.BufferedImage;
|
|
|
import java.io.IOException;
|
|
|
-import java.util.Date;
|
|
|
import java.util.Random;
|
|
|
import javax.imageio.ImageIO;
|
|
|
import javax.servlet.ServletOutputStream;
|
|
|
@@ -28,9 +22,11 @@ public class CaptchaUtil {
|
|
|
/**
|
|
|
* 随机字符字典
|
|
|
*/
|
|
|
- private static final char[] CHARS = { '2', '3', '4', '5', '6', '7', '8',
|
|
|
- '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M',
|
|
|
- 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
|
|
|
+ private static final String codes = "23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ"; //验证码数组
|
|
|
+
|
|
|
+ private static BufferedImage buffImg;
|
|
|
+
|
|
|
+ private static String textCode;
|
|
|
|
|
|
/**
|
|
|
* 随机数
|
|
|
@@ -38,33 +34,31 @@ public class CaptchaUtil {
|
|
|
private static Random random = new Random();
|
|
|
|
|
|
/**
|
|
|
- * 获取6位随机数
|
|
|
+ * 生成4位随机验证码
|
|
|
+ *
|
|
|
+ * @return 验证码
|
|
|
*/
|
|
|
- private static String getRandomString()
|
|
|
- {
|
|
|
- StringBuilder buffer = new StringBuilder();
|
|
|
- for(int i = 0; i < 4; i++)
|
|
|
- {
|
|
|
- buffer.append(CHARS[random.nextInt(CHARS.length)]);
|
|
|
- }
|
|
|
- return buffer.toString();
|
|
|
- }
|
|
|
+ private static String getRandomCode() {
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
- /**
|
|
|
- * 获取随机数颜色
|
|
|
- */
|
|
|
- private static Color getRandomColor()
|
|
|
- {
|
|
|
- return new Color(255,255,255);
|
|
|
+ int i = 0;
|
|
|
+ while (i++ < 4) {
|
|
|
+ int index = random.nextInt(codes.length());
|
|
|
+ sb.append(codes.charAt(index));
|
|
|
+ }
|
|
|
+ return sb.toString();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 返回某颜色的反色
|
|
|
+ * 生成随机颜色(深色)
|
|
|
+ * @return 颜色
|
|
|
*/
|
|
|
- private static Color getReverseColor(Color c)
|
|
|
- {
|
|
|
- return new Color(255 - c.getRed(), 255 - c.getGreen(),
|
|
|
- 255 - c.getBlue());
|
|
|
+ private static Color getRandomColor() {
|
|
|
+ // 产生随机的颜色值,让输出的每个字符的颜色值都将不同。
|
|
|
+ int red = random.nextInt(200);
|
|
|
+ int green = random.nextInt(200);
|
|
|
+ int blue = random.nextInt(200);
|
|
|
+ return new Color(red, green, blue);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -80,69 +74,115 @@ public class CaptchaUtil {
|
|
|
|
|
|
response.setContentType("image/jpeg");
|
|
|
|
|
|
- String randomString = getRandomString();
|
|
|
- request.getSession(true).setAttribute(key, randomString);
|
|
|
+ drawImage(new Color(255, 255, 255), new Color(200, 200, 200));
|
|
|
+ request.getSession().setAttribute(key, textCode);
|
|
|
+
|
|
|
+ // 转成JPEG格式
|
|
|
+ ServletOutputStream out = response.getOutputStream();
|
|
|
+ ImageIO.write(buffImg, "jpeg", out);
|
|
|
+ out.flush();
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
+ /**
|
|
|
+ * 绘制图片
|
|
|
+ * @param backColor 背景颜色
|
|
|
+ * @param lineColor 线条颜色
|
|
|
+ */
|
|
|
+ private static void drawImage(Color backColor, Color lineColor) {
|
|
|
int width = 100;
|
|
|
int height = 30;
|
|
|
- int lines = 10;
|
|
|
+ int interLine = 10;
|
|
|
+ textCode = getRandomCode();
|
|
|
+ buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
|
|
+ Graphics g = buffImg.getGraphics();
|
|
|
|
|
|
- Color color = getRandomColor();
|
|
|
- Color reverse = getReverseColor(color);
|
|
|
-
|
|
|
- BufferedImage bi = new BufferedImage(width, height,
|
|
|
- BufferedImage.TYPE_INT_RGB);
|
|
|
- Graphics2D g = bi.createGraphics();
|
|
|
- g.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 18));
|
|
|
- g.setColor(color);
|
|
|
+ // 设置背景颜色
|
|
|
+ g.setColor(backColor == null ? getRandomColor() : backColor);
|
|
|
g.fillRect(0, 0, width, height);
|
|
|
- g.setColor(reverse);
|
|
|
- Random r = new Random(new Date().getTime());
|
|
|
-
|
|
|
- // 生成验证码
|
|
|
- char[] randomChars = randomString.toCharArray();
|
|
|
- for (int i = 0; i < randomChars.length; i++) {
|
|
|
- int y = 10 + r.nextInt(20);// 10~30范围内的一个整数,作为y坐标
|
|
|
- Color c = new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255));
|
|
|
- g.setColor(c);
|
|
|
- g.drawString("" + randomChars[i], 5 + i * width / 4, y);
|
|
|
- }
|
|
|
|
|
|
- /**
|
|
|
- * 加圆点
|
|
|
- */
|
|
|
- for (int i = 0, n = random.nextInt(100); i < n; i++) {
|
|
|
- g.drawOval(random.nextInt(width), random.nextInt(height), 1, 1);
|
|
|
+ // 绘制线条
|
|
|
+ int x = random.nextInt(4), y;
|
|
|
+ int x1 = width - random.nextInt(4), y1;
|
|
|
+ for (int i = 0; i < interLine; i++) {
|
|
|
+ g.setColor(lineColor == null ? getRandomColor() : lineColor);
|
|
|
+ y = random.nextInt(height - random.nextInt(4));
|
|
|
+ y1 = random.nextInt(height - random.nextInt(4));
|
|
|
+ g.drawLine(x, y, x1, y1);
|
|
|
}
|
|
|
|
|
|
- // 干扰线
|
|
|
- for (int i = 0; i < lines; i++) {
|
|
|
- Color c = new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255));
|
|
|
- g.setColor(c);
|
|
|
- g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height));
|
|
|
+ int fsize = (int) (height * 0.8);//字体大小为图片高度的80%
|
|
|
+ int fx = (int) ((width / textCode.length()) * (Math.random() * 0.3 + 0.2));
|
|
|
+ int fy;
|
|
|
+ g.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, fsize));
|
|
|
+ //写字符
|
|
|
+ for (int i = 0; i < textCode.length(); i++) {
|
|
|
+ fy = fsize;//每个字符高低是否随机
|
|
|
+ g.setColor(getRandomColor());
|
|
|
+ g.drawString(textCode.charAt(i) + "", fx, fy);
|
|
|
+ fx += (width / textCode.length()) * (Math.random() * 0.3 + 0.8); //依据宽度浮动
|
|
|
}
|
|
|
|
|
|
- // 转成JPEG格式
|
|
|
- ServletOutputStream out = response.getOutputStream();
|
|
|
- ImageIO.write(bi, "jpeg", out);
|
|
|
- out.flush();
|
|
|
+ //扭曲图片
|
|
|
+ shearX(g, width, height, backColor);
|
|
|
+ shearY(g, width, height, backColor);
|
|
|
+
|
|
|
+ // 添加噪点
|
|
|
+ float yawpRate = 0.05f;// 噪声率
|
|
|
+ int area = (int) (yawpRate * width * height);//噪点数量
|
|
|
+ for (int i = 0; i < area; i++) {
|
|
|
+ int xxx = random.nextInt(width);
|
|
|
+ int yyy = random.nextInt(height);
|
|
|
+ int rgb = getRandomColor().getRGB();
|
|
|
+ buffImg.setRGB(xxx, yyy, rgb);
|
|
|
+ }
|
|
|
+ g.dispose();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 校验图片验证码
|
|
|
- * @param request
|
|
|
- * @param key 获取图片验证码存session的key
|
|
|
- * @param code 校验的验证码
|
|
|
+ * 横向扭曲图片
|
|
|
+ * @param g 画布
|
|
|
+ * @param w1 宽度
|
|
|
+ * @param h1 高度
|
|
|
+ * @param color 背景颜色
|
|
|
*/
|
|
|
- public static void checkCode(HttpServletRequest request, String key, String code) {
|
|
|
- String captcha = (String) request.getSession().getAttribute(key);
|
|
|
- if (StringUtils.isEmpty(captcha)) {
|
|
|
- throw new VisibleError("图片验证码过期");
|
|
|
- }
|
|
|
- if (code != null && !code.equalsIgnoreCase(captcha)) {
|
|
|
- throw new VisibleError("请输入正确的验证码");
|
|
|
+ private static void shearX(Graphics g, int w1, int h1, Color color) {
|
|
|
+ Random random = new Random();
|
|
|
+ int period = 2;
|
|
|
+
|
|
|
+ int frames = 1;
|
|
|
+ int phase = random.nextInt(2);
|
|
|
+
|
|
|
+ for (int i = 0; i < h1; i++) {
|
|
|
+ double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (2.2831853071795862D * (double) phase) / (double) frames);
|
|
|
+ g.copyArea(0, i, w1, 1, (int) d, 0);
|
|
|
+ g.setColor(color);
|
|
|
+ g.drawLine((int) d, i, 0, i);
|
|
|
+ g.drawLine((int) d + w1, i, w1, i);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- request.getSession().removeAttribute(key);
|
|
|
+ /**
|
|
|
+ * 纵向扭曲图片
|
|
|
+ * @param g 画布
|
|
|
+ * @param w1 宽度
|
|
|
+ * @param h1 高度
|
|
|
+ * @param color 背景颜色
|
|
|
+ */
|
|
|
+ private static void shearY(Graphics g, int w1, int h1, Color color) {
|
|
|
+ Random random = new Random();
|
|
|
+ int period = random.nextInt(10) + 10; // 50;
|
|
|
+
|
|
|
+ int frames = 20;
|
|
|
+ int phase = 1;
|
|
|
+ for (int i = 0; i < w1; i++) {
|
|
|
+ double d = (double) (period >> 1)
|
|
|
+ * Math.sin((double) i / (double) period
|
|
|
+ + (2.2831853071795862D * (double) phase) / (double) frames);
|
|
|
+ g.copyArea(i, 0, 1, h1, 0, (int) d);
|
|
|
+ g.setColor(color);
|
|
|
+ g.drawLine(i, (int) d, i, 0);
|
|
|
+ g.drawLine(i, (int) d + h1, i, h1);
|
|
|
+ }
|
|
|
}
|
|
|
}
|