当前位置:网站首页>生成验证码工具类
生成验证码工具类
2022-08-08 18:41:00 【糖葫芦零零七】
验证码的作用: 防止机器自动注册,攻击服务器
下图为主程序展示: 在E盘下生成一个长为100,宽为50的a.jpg图片,图片为四位验证码。
图片生成展示:
完整代码
package util;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Random;
/** * 生成验证码工具类 */
public class CheckCodeUtil {
public static final String VERIFY_CODES = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static Random random = new Random();
public static void main(String[] args) throws IOException{
OutputStream fos = new FileOutputStream("e://a.jpg");
String checkCode = CheckCodeUtil.outputVerifyImage(100, 50, fos, 4);
System.out.println(checkCode);
}
/** * 输出随机验证码图片流,并返回验证码值(一般传入输出流,响应response页面端,Web项目用的较多) * @param width 图片的宽度 * @param height 图片的高度 * @param os 输出流 * @param verifySize 生成的数据长度 * @return 验证码 * @throws IOException */
public static String outputVerifyImage(int width, int height, OutputStream os, int verifySize) throws IOException {
String verifyCode = generateVerifyCode(verifySize);
outputImage(width, height, os, verifyCode);
return verifyCode;
}
/** * 使用系统默认字符源生成验证码 * * @param verifySize 验证码长度 * @return */
public static String generateVerifyCode(int verifySize) {
return generateVerifyCode(verifySize, VERIFY_CODES);
}
/** * 使用指定源生成验证码 * @param verifySize 验证码长度 * @param sources 验证码字符源 * @return */
public static String generateVerifyCode(int verifySize, String sources) {
// 未设定展示源的字码,赋默认值大写字母+数字
if (sources == null || sources.length() == 0) {
sources = VERIFY_CODES;
}
int codesLen = sources.length();
Random rand = new Random(System.currentTimeMillis());
StringBuilder verifyCode = new StringBuilder(verifySize);
for (int i = 0; i < verifySize; i++) {
verifyCode.append(sources.charAt(rand.nextInt(codesLen - 1)));
}
return verifyCode.toString();
}
/** * 生成随机验证码文件,并返回验证码值 (生成图片形式,用的较少) * * @param w * @param h * @param outputFile * @param verifySize * @return * @throws IOException */
public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException {
String verifyCode = generateVerifyCode(verifySize);
outputImage(w, h, outputFile, verifyCode);
return verifyCode;
}
/** * 生成指定验证码图像文件 * * @param w * @param h * @param outputFile * @param code * @throws IOException */
public static void outputImage(int w, int h, File outputFile, String code) throws IOException {
if (outputFile == null) {
return;
}
File dir = outputFile.getParentFile();
//文件不存在
if (!dir.exists()) {
//创建
dir.mkdirs();
}
try {
outputFile.createNewFile();
FileOutputStream fos = new FileOutputStream(outputFile);
outputImage(w, h, fos, code);
fos.close();
} catch (IOException e) {
throw e;
}
}
/** * 输出指定验证码图片流 * * @param w * @param h * @param os * @param code * @throws IOException */
public static void outputImage(int w, int h, OutputStream os, String code) throws IOException {
int verifySize = code.length();
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Random rand = new Random();
Graphics2D g2 = image.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// 创建颜色集合,使用java.awt包下的类
Color[] colors = new Color[5];
Color[] colorSpaces = new Color[]{
Color.WHITE, Color.CYAN,
Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,
Color.PINK, Color.YELLOW};
float[] fractions = new float[colors.length];
for (int i = 0; i < colors.length; i++) {
colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];
fractions[i] = rand.nextFloat();
}
Arrays.sort(fractions);
// 设置边框色
g2.setColor(Color.GRAY);
g2.fillRect(0, 0, w, h);
Color c = getRandColor(200, 250);
// 设置背景色
g2.setColor(c);
g2.fillRect(0, 2, w, h - 4);
// 绘制干扰线
Random random = new Random();
// 设置线条的颜色
g2.setColor(getRandColor(160, 200));
for (int i = 0; i < 20; i++) {
int x = random.nextInt(w - 1);
int y = random.nextInt(h - 1);
int xl = random.nextInt(6) + 1;
int yl = random.nextInt(12) + 1;
g2.drawLine(x, y, x + xl + 40, y + yl + 20);
}
// 添加噪点
// 噪声率
float yawpRate = 0.05f;
int area = (int) (yawpRate * w * h);
for (int i = 0; i < area; i++) {
int x = random.nextInt(w);
int y = random.nextInt(h);
// 获取随机颜色
int rgb = getRandomIntColor();
image.setRGB(x, y, rgb);
}
// 添加图片扭曲
shear(g2, w, h, c);
g2.setColor(getRandColor(100, 160));
int fontSize = h - 4;
Font font = new Font("Algerian", Font.ITALIC, fontSize);
g2.setFont(font);
char[] chars = code.toCharArray();
for (int i = 0; i < verifySize; i++) {
AffineTransform affine = new AffineTransform();
affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize / 2, h / 2);
g2.setTransform(affine);
g2.drawChars(chars, i, 1, ((w - 10) / verifySize) * i + 5, h / 2 + fontSize / 2 - 10);
}
g2.dispose();
ImageIO.write(image, "jpg", os);
}
/** * 随机颜色 * * @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);
}
private static int getRandomIntColor() {
int[] rgb = getRandomRgb();
int color = 0;
for (int c : rgb) {
color = color << 8;
color = color | c;
}
return color;
}
private static int[] getRandomRgb() {
int[] rgb = new int[3];
for (int i = 0; i < 3; i++) {
rgb[i] = random.nextInt(255);
}
return rgb;
}
private static void shear(Graphics g, int w1, int h1, Color color) {
shearX(g, w1, h1, color);
shearY(g, w1, h1, color);
}
private static void shearX(Graphics g, int w1, int h1, Color color) {
int period = random.nextInt(2);
boolean borderGap = true;
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
+ (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);
}
}
}
private static void shearY(Graphics g, int w1, int h1, Color color) {
int period = random.nextInt(40) + 10; // 50;
boolean borderGap = true;
int frames = 20;
int phase = 7;
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);
}
}
}
}
边栏推荐
- 21天学习挑战赛——机器学习02
- 达梦数据库 DmAPservice服务,启停影响 DMSERVER库服务吗?
- view, index
- We want to replace the RDS database and upgrade from sqlserver 2016 web to 2017 enterprise cluster version, with expert consultation
- hdu1042 N! (large number)
- 软件测试主要是做什么的?
- Shell脚本三剑客(grep、sed、awk)
- A Preliminary Study on Pannellum, a Lightweight Panorama Viewer
- DHCP服务初探
- 8月报考季,软考选科目避坑指南来啦
猜你喜欢
Laravel 5.8笔记
Research on ORACLE subqueries that lead to inability to push predicates
小白转行做3D游戏建模,有没有前途?
能力一般,却可以大厂随便横跳?强在哪里?
Learn about layered architecture & SOA architecture together
Laravel queue consumption instance and timed task add task consumption
Shell正则表达式
Geometric g6 will carry harmonyos system, a comprehensive upgrade competitiveness of products
Shell脚本三剑客(grep、sed、awk)
堆排序(Heap Sort)实现
随机推荐
How to add F4 Value Help to the input parameters of the report in the ABAP report
The origin and creation of Smobiler's complex controls
Redis Server启动过程
一些小题22.08.07
USB CY68013设备描述符识别失败
重读GPDB 和 TiDB 论文引发的 HTAP 数据库再思考
Learn about layered architecture & SOA architecture together
hdu2647 N!Again
Dataworks上的ODPS spark处理数据会比直接用ODPS SQL效率高吗?
uniapp parent component uses prop to pass asynchronous data to child components
卡通渲染的历史
一起了解分层架构&SOA架构
Open Office XML 格式中的 Style 设计原理
OpenInfra Days China 2022即将开启,与 openEuler 共话开源技术
PX4模块设计之十九:Replay模块
nyoj 712 探 寻 宝 藏(双线dp 第六届河南省程序设计大赛)
面经刺客 | 关于——字节飞书基础架构产品 日常实习面经
响应式pbootcms模板建筑装饰类网站
oracle视图v$active_session_history,dba_hist_active_session_history如何记录IP地址
MIMO雷达波束赋形