验证码生成工具

本工具可以生成:

  • 数字+字符
  • 纯数字
  • 纯字符

验证码样式:

  • 字符串
  • base64 字符图片验证码

主要方法:

  • generateCaptchaImage:获取图片验证码
  • generateCaptchaImageVerifyCode:获取图片验证码:(更多自定义参数)
  • getVerifyCode:获取验证码
  • getStringVerifyCode:获取默认长度验证码
  • getNumberVerifyCode:获取默认长度纯数字验证码
  • getStringAndNumberVerifyCode:获取默认长度,数字加字符
@Slf4j
public class VerifyCodeUtils {// 加载字体并缓存private static volatile Font cacheFont = null;//默认宽度private static final Integer imgWidth = 150;//默认高度private static final Integer imgHeight = 50;//随机字符串和数字private static final String STRING_NUMBER_VERIFY_CODE = "123456789ABCDEFGHJKLNPQRSTUVXYZ";//随机字符串private static final String STRING_VERIFY_CODE = "ABCDEFGHIJKLMNPOQRSTUVWXYZ";//随机数private static Random random = new Random();//默认验证码长度private static int DEFAULT_VERIFY_CODE_LENGTH = 4;//验证码最大长度private static int MAX_VERIFY_CODE_LENGTH = 6;//默认干扰线系数private static float DEFAULT_INTERFERE_RATE = 0.1f;//默认噪声系数private static float DEFAULT_NOISE_RATE = 0.3f;/*** 纯数字验证码* @param length 4-6位,默认4位* @return*/private static String generateNumberVerifyCode(int length) {String code;if (length == 6){code = String.valueOf(ThreadLocalRandom.current().nextInt(0, 999999));}else if (length == 5){code = String.valueOf(ThreadLocalRandom.current().nextInt(0, 99999));}else {code = String.valueOf(ThreadLocalRandom.current().nextInt(0, 9999));}if (code.length() == length) {return code;} else {StringBuilder str = new StringBuilder();for(int i = 0; i < length - code.length(); ++i) {str.append("0");}return str + code;}}/*** 生成随机验证码* @param length* @param sources* @return*/private static String generateVerifyCode(int length, String sources) {if (sources == null || sources.length() == 0) {sources = STRING_NUMBER_VERIFY_CODE;}int codeLen = sources.length();Random rand = new Random();StringBuilder verifyCode = new StringBuilder(length);for (int i = 0; i < length; i++) {verifyCode.append(sources.charAt(rand.nextInt(codeLen - 1)));}return verifyCode.toString();}/*** 默认长度4,数字加字符串* @return*/public static String getStringAndNumberVerifyCode() {return generateVerifyCode(DEFAULT_VERIFY_CODE_LENGTH, STRING_NUMBER_VERIFY_CODE);}/*** 默认长度4,获取纯数字验证码* @return*/public static String getNumberVerifyCode() {return generateNumberVerifyCode(DEFAULT_VERIFY_CODE_LENGTH);}/*** 默认长度4,字符串* @return*/public static String getStringVerifyCode() {return generateVerifyCode(DEFAULT_VERIFY_CODE_LENGTH, STRING_VERIFY_CODE);}/*** 获取验证码* @param length 验证码长度 最长不超过6位 ,默认4位* @param type 验证码类型 0-数字+字符,1-纯数字,2-纯字符 默认0* @return*/public static String getVerifyCode(int length, int type) {if (length == 0){length = DEFAULT_VERIFY_CODE_LENGTH;}if (length < DEFAULT_VERIFY_CODE_LENGTH){throw new DescribeException("length不能小于"+DEFAULT_VERIFY_CODE_LENGTH, ServerCodeEnum.PARAM_ERROR.getCode());}if (length > MAX_VERIFY_CODE_LENGTH){throw new DescribeException("length不能大于"+MAX_VERIFY_CODE_LENGTH,ServerCodeEnum.PARAM_ERROR.getCode());}if (type == 1){return generateNumberVerifyCode(length);}if (type == 2){return generateVerifyCode(length, STRING_VERIFY_CODE);}return generateVerifyCode(length, STRING_NUMBER_VERIFY_CODE);}/*** 返回base64图片验证码* @param code 验证码* @param imgWidth 宽度* @param imgHeight 高度* @return*/public static String generateCaptchaImageVerifyCode(String code, Integer imgWidth, Integer imgHeight){if (imgWidth == null){imgWidth = VerifyCodeUtils.imgWidth;}if (imgHeight == null){imgHeight = VerifyCodeUtils.imgHeight;}return generateCaptchaImage(imgWidth, imgHeight, code,DEFAULT_INTERFERE_RATE , DEFAULT_NOISE_RATE);}/*** 返回base64图片验证码* @param code 验证码* @param imgWidth 宽度* @param imgHeight 高度* @param interfereRate 干扰性系数0.0-1.0* @param noiseRate 噪声系数 0.0-1.0* @return*/public static String generateCaptchaImage(String code, int imgWidth, int imgHeight,float interfereRate, float noiseRate){return generateCaptchaImage(imgWidth, imgHeight, code, interfereRate, noiseRate);}/*** 生成验证码图片* @param imgWidth 宽度* @param imgHeight 高度* @param code 验证码* @param interfereRate 干扰系数 0.1-1* @param noiseRate 噪声系数 0.1-1*/private static String generateCaptchaImage(int imgWidth, int imgHeight, String code, float interfereRate, float noiseRate){String base64Img = null;try {int length = code.length();BufferedImage image = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);Random rand = new Random();Graphics2D graphics2D = image.createGraphics();graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);// 设置边框色graphics2D.setColor(Color.GRAY);graphics2D.fillRect(0, 0, imgWidth, imgHeight);// 设置背景色Color c = new Color(235, 235, 235);graphics2D.setColor(c);graphics2D.fillRect(0, 1, imgWidth, imgHeight - 2);//绘制干扰interfere(image, graphics2D, imgWidth, imgHeight, interfereRate, noiseRate);//使图片扭曲shear(graphics2D, imgWidth, imgHeight, c);//字体颜色graphics2D.setColor(getRandColor(30, 100));//字体大小int fontSize = imgHeight >= 50 ?  imgHeight - 8 : imgHeight >= 30 ? imgHeight - 6 : imgHeight - 4;//字体 Fixedsys/AlgerianFont font = new Font("Fixedsys", Font.ITALIC, fontSize);graphics2D.setFont(font);char[] chars = code.toCharArray();for (int i = 0; i < length; i++) {//设置旋转AffineTransform affine = new AffineTransform();//控制在-0.3-0.3double theta = ((Math.PI / 4 * rand.nextDouble())*0.3) * (rand.nextBoolean() ? 1 : -1);affine.setToRotation(theta, (imgWidth / length) * i + fontSize / 2, imgHeight / 2);graphics2D.setTransform(affine);int x = ((imgWidth - 10) / length) * i + 4;//文字居中FontMetrics fm = graphics2D.getFontMetrics();int stringAscent = fm.getAscent();int stringDescent = fm.getDescent ();int y = imgHeight / 2 + (stringAscent - stringDescent) / 2;graphics2D.drawChars(chars, i, 1, x, y);}graphics2D.dispose();ByteArrayOutputStream outputStream = new ByteArrayOutputStream();ImageIO.write(image, "jpg", outputStream);Base64.Encoder encoder = Base64.getEncoder();base64Img = encoder.encodeToString(outputStream.toByteArray());base64Img = base64Img.replaceAll("\n", "").replaceAll("\r", "");}catch (Exception e){log.error("生成图片验证码异常:", e);}return base64Img;}/*** 绘制干扰线和噪点* @param image 图像* @param graphics2D 二维图* @param imgWidth 宽度* @param imgHeight 高度* @param interfereRate 干扰线率 0.1-1* @param noiseRate 噪声率 0.1-1*/private static void interfere(BufferedImage image,Graphics2D graphics2D, int imgWidth, int imgHeight, float interfereRate, float noiseRate){Random random = new Random();graphics2D.setColor(getRandColor(160, 200));int line = (int) (interfereRate * 100);for (int i = 0; i < line; i++) {int x = random.nextInt(imgWidth - 1);int y = random.nextInt(imgHeight - 1);int xl = random.nextInt(6) + 1;int yl = random.nextInt(12) + 1;graphics2D.drawLine(x, y, x + xl + 40, y + yl + 20);}int area = (int) (noiseRate * imgWidth * imgHeight)/10;for (int i = 0; i < area; i++) {int x = random.nextInt(imgWidth);int y = random.nextInt(imgHeight);int rgb = getRandomIntColor();image.setRGB(x, y, rgb);}}/*** 获取随机颜色* @param fc* @param bc* @return*/private static Color getRandColor(int fc, int bc) {if (fc > 255) {fc = 255;}if (bc > 255) {bc = 255;}int r = fc + random.nextInt(bc - fc);int g = fc + random.nextInt(bc - fc);int b = fc + random.nextInt(bc - fc);return new Color(r, g, b);}/*** 获取rgb* @return*/private static int getRandomIntColor() {int[] rgb = getRandomRgb();int color = 0;for (int c : rgb) {color = color << 8;color = color | c;}return color;}/*** 获取随机rgb颜色* @return*/private static int[] getRandomRgb() {int[] rgb = new int[3];for (int i = 0; i < 3; i++) {rgb[i] = random.nextInt(255);}return rgb;}/*** 使图片扭曲* @param g* @param w1* @param h1* @param color*/private static void shear(Graphics g, int w1, int h1, Color color) {distortionX(g, w1, h1, color);distortionY(g, w1, h1, color);}/*** 使图片x轴扭曲* @param g* @param w1* @param h1* @param color*/private static void distortionX(Graphics g, int w1, int h1, Color color) {int period = random.nextInt(4);boolean borderGap = true;int frames = 2;int phase = random.nextInt(4);for (int i = 0; i < h1; i++) {double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);g.copyArea(0, i, w1, 1, (int) d, 0);if (borderGap) {g.setColor(color);g.drawLine((int) d, i, 0, i);g.drawLine((int) d + w1, i, w1, i);}}}/*** 使图片y轴扭曲* @param g* @param w1* @param h1* @param color*/private static void distortionY(Graphics g, int w1, int h1, Color color) {int period = random.nextInt(20) + 10;boolean borderGap = true;int frames = 20;int phase = 8;for (int i = 0; i < w1; i++) {double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);g.copyArea(i, 0, 1, h1, 0, (int) d);if (borderGap) {g.setColor(color);g.drawLine(i, (int) d, i, 0);g.drawLine(i, (int) d + h1, i, h1);}}}/*** 创建字体* @param style 字体样式* @param size  字体大小* @return 字体*/private static Font createFont(int style, int size) {if (cacheFont != null) {return cacheFont.deriveFont(style, size);} else {cacheFont = loadFont();return cacheFont;}}/*** 加载字体,解决Centos 7.2 以后,使用OpenJDK11 生成不了验证码问题* @return 生成验证码的字体*/private static Font loadFont() {if (StringUtils.startsWithIgnoreCase(System.getProperty("os.name"), "windows")) {// windows 操作系统直接返回即可return new Font("Fixedsys", Font.BOLD, 0);} else {// linux 操作系统字体需要特殊处理try {InputStream inputStream = null;Resource fontFile = new DefaultResourceLoader().getResource("classpath:ALGER.TTF");try {// 加载字体配置文件Resource fontProperties = new DefaultResourceLoader().getResource("classpath:fontconfig.properties");System.setProperty("sun.awt.fontconfig", fontProperties.getURL().getPath());inputStream = fontFile.getInputStream();return Font.createFont(Font.TRUETYPE_FONT, inputStream);} catch (Exception e) {log.error("Create Font Error", e);} finally {IOUtils.closeQuietly(inputStream);}} catch (Exception e) {log.error("Load Font Error", e);}return null;}}/*** 生成验证码* @param code* @param imgWidth* @param imgHeight* @return*/private static String generateCaptchaImage(String code, Integer imgWidth, Integer imgHeight) {if (StringUtils.isBlank(code)) {return null;}imgWidth = imgWidth == null ? VerifyCodeUtils.imgWidth : imgWidth;imgHeight = imgHeight == null ? VerifyCodeUtils.imgHeight: imgHeight;Integer codeLength = code.length();BufferedImage bufferedImg = null;String base64Img = null;try {int x = 0;// 每个字符的宽度x = imgWidth / (codeLength + 1);int fontHeight = 0;// 字体的高度fontHeight = imgHeight - 10;float codeY;codeY = (float) (imgHeight - 10.1);// 生成一张图片bufferedImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);Graphics2D graph = bufferedImg.createGraphics();// 填充图片颜色graph.setColor(Color.WHITE);graph.fillRect(0, 0, imgWidth, imgHeight);// 创建字体Font font = new Font("Fixedsys", Font.TRUETYPE_FONT, fontHeight);graph.setFont(font);Random random = new Random();// 随机画干扰的圈圈int red = 0;int green = 0;int blue = 0;for (int i = 0; i < 10; i++) {int xs = random.nextInt(imgWidth);int ys = random.nextInt(imgHeight);int xe = random.nextInt(imgWidth / 16);int ye = random.nextInt(imgHeight / 16);red = random.nextInt(255);green = random.nextInt(255);blue = random.nextInt(255);graph.setColor(new Color(red, green, blue));graph.drawOval(xs, ys, xe, ye);}// 画随机线for (int i = 0; i < 20; i++) {int xs = random.nextInt(imgWidth);int ys = random.nextInt(imgHeight);int xe = xs + random.nextInt(imgWidth / 16);int ye = ys + random.nextInt(imgHeight / 16);red = random.nextInt(255);green = random.nextInt(255);blue = random.nextInt(255);graph.setColor(new Color(red, green, blue));graph.drawLine(xs, ys, xe, ye);}// 产生随机的颜色值,让输出的每个字符的颜色值都将不同。for (int i = 0; i < codeLength; i++) {red = random.nextInt(225);green = random.nextInt(225);blue = random.nextInt(225);graph.setColor(new Color(red, green, blue));String c = String.valueOf(code.charAt(i));graph.drawString(c, (float) (i + 0.5) * x, codeY);}ByteArrayOutputStream outputStream = new ByteArrayOutputStream();ImageIO.write(bufferedImg, "jpg", outputStream);Base64.Encoder encoder = Base64.getEncoder();base64Img = encoder.encodeToString(outputStream.toByteArray());base64Img = base64Img.replaceAll("\n", "").replaceAll("\r", "");} catch (Exception e) {log.error("生成验证码异常:", e);}
//        return "data:image/jpg;base64," + base64Img;return base64Img;}
}

Java验证码(图片、字符串)生成工具相关推荐

  1. java验证码图片滑动验证码_图片滑动验证码的生成

    使用Java生成图片滑动验证码 image.png 目前接到了一个新的小需求,要在登录时进行滑动图片验证. 搜了一下网上的demo,没有太多很完整的demo.就参考各种文档自己拼凑了一个出来.整理一下 ...

  2. java 验证码 算术_java生成图形验证码(算数运算图形验证码 + 随机字符图形验证码)...

    平凡也就两个字: 懒和惰; 成功也就两个字: 苦和勤; 优秀也就两个字: 你和我. 跟着我从0学习JAVA.spring全家桶和linux运维等知识,带你从懵懂少年走向人生巅峰,迎娶白富美! 关注微信 ...

  3. JAVA接口签名sign生成工具类

    签名规则 1.线下分配appid和appsecret,针对不同的调用方分配不同的appid和appsecret 2.加入timestamp(时间戳),10分钟内数据有效 3.加入流水号nonce(防止 ...

  4. java接口文档生成工具_接口文档生成

    一.为什么要写接口文档? 1.正规的团队合作或者是项目对接,接口文档是非常重要的,一般接口文档都是通过开发人员写的.一个工整的文档显得是非重要. 2.项目开发过程中前后端工程师有一个统一的文件进行沟通 ...

  5. java接口文档生成工具_【分享】接口文档生成工具apipost

    一.为什么要写接口文档? 正规的团队合作或者是项目对接,接口文档是非常重要的,一般接口文档都是通过开发人员写的.一个工整的文档显得是非重要. 项目开发过程中前后端工程师有一个统一的文件进行沟通交流开发 ...

  6. Java验证码图片工具类

    工具类源码 import org.apache.commons.codec.binary.Base64;import javax.imageio.ImageIO; import java.awt.*; ...

  7. java 验证码图片识别_JavaSE图像验证码简单识别程序详解

    本文为大家分享了JavaSE图像验证码简单识别程序,供大家参考,具体内容如下 首先你应该对图片进行样本采集,然后将样本进行灰度处理,也就是变成黑白两色. 然后你就可以使用该类,对目标文件进行分析.具体 ...

  8. JAVA二维码生成工具

    需要导入的pom依赖 <dependency><groupId>com.google.zxing</groupId><artifactId>javase ...

  9. Java中操作字符串的工具类-判空、截取、格式化、转换驼峰、转集合和list、是否包含

    场景 某些常用的对字符串进行处理的方法抽离出来成工具类,方便在多处应用. 常用的操作为: 判断是否为空 截取字符串 格式化文本 字符串转set 字符串转list 下划线转驼峰命名 是否包含字符串 注: ...

最新文章

  1. 在Excel单元格中使用下拉框
  2. img summernote 加类_控制好情绪 的动态 - SegmentFault 思否
  3. 得到 yyyy/mm/dd 格式时间
  4. Blazor带我重玩前端(三)
  5. Windows2003如何安装IIS和ftp
  6. imwrite函数 matlab_用matlab做一个脉动磁势分解的动画
  7. java web 教程_Java Web服务教程
  8. 沁恒CH32V307母板+OPA4377运放模块-开源
  9. 向日葵远程调用Visual studio2019时白屏透明黑屏解决方案
  10. 基于DMD实现透过多模光纤(MMF)的聚焦
  11. iOS10.2越狱图文教程 iOS10.2越狱工具
  12. 当深度学习遇见自动文本摘要
  13. jquery.printarea.js 局部打印去掉页眉页脚
  14. matlab模拟出现较大误差是什么原因,关于使用lsqcurvefit拟合曲线出现误差巨大的问题...
  15. 面向对象设计原则(一)单一原则
  16. 硬件设计之JTAG转USB转换芯片
  17. 解决git拉取代码时报:Auto packing the repository in background for optimum performance
  18. [docker] 解决 docker 部署访问提示 Empty reply from server,但是本地运行能够正常访问
  19. 2019-12-03 Python3 作业 爬取豆瓣读书所有出版商信息
  20. 免费学习网站-中国大学mooc

热门文章

  1. MIPI-DSI/CSI协议介绍
  2. 浙江大学计算机学院 00级,浙江大学教师划分为13个等级
  3. Joda-Time 工具类的使用
  4. 杜克大学计算机专业本科入学条件,杜克大学本科申请条件有哪些?
  5. 大学生职业规划策划书
  6. 使用pdfBox实现pdf转图片出现中文方块乱码 简单修改源码解决
  7. Linux下同时打开编辑多个文件 【VSP、vim -o】
  8. python自动化表格处理软件_Python自动化处理Excel报表,我的工作更轻松了!
  9. 上海交大计算机考试科目,上海交通大学需要选什么科目?附上海交通大学必选科目...
  10. android 布局排排,[android]如何使LinearLayout布局从右向左水平排列,而不是从左向右排列...