【Java】生成图形验证码
本章介绍一个能生成比较好看的图形验证码类生成验证码工具类 1 package com.util;
2
3 import java.awt.Color;
4 import java.awt.Font;
5 import java.awt.Graphics;
6 import java.awt.Graphics2D;
7 import java.awt.RenderingHints;
8 import java.awt.geom.AffineTransform;
9 import java.awt.image.BufferedImage;
10 import java.io.File;
11 import java.io.FileOutputStream;
12 import java.io.IOException;
13 import java.io.OutputStream;
14 import java.util.Arrays;
15 import java.util.Random;
16
17 import javax.imageio.ImageIO;
18
19
20 public class VerifyCodeUtils {
21
22 //使用到Algerian字体,系统里没有的话需要安装字体,字体只显示大写,去掉了1,0,i,o几个容易混淆的字符
23 public static final String VERIFY_CODES = “23456789ABCDEFGHJKLMNPQRSTUVWXYZ”;
24 private static Random random = new Random();
25
26
27 /**
28 * 使用系统默认字符源生成验证码
29 * @param verifySize 验证码长度
30 * @return
31 /
32 public static String generateVerifyCode(int verifySize){
33 return generateVerifyCode(verifySize, VERIFY_CODES);
34 }
35
36 /*
37 * 使用指定源生成验证码
38 * @param verifySize 验证码长度
39 * @param sources 验证码字符源
40 * @return
41 /
42 public static String generateVerifyCode(int verifySize, String sources){
43 if(sources == null || sources.length() == 0){
44 sources = VERIFY_CODES;
45 }
46 int codesLen = sources.length();
47 Random rand = new Random(System.currentTimeMillis());
48 StringBuilder verifyCode = new StringBuilder(verifySize);
49 for(int i = 0; i < verifySize; i++){
50 verifyCode.append(sources.charAt(rand.nextInt(codesLen-1)));
51 }
52 return verifyCode.toString();
53 }
54
55 /*
56 * 生成随机验证码文件,并返回验证码值
57 * @param w
58 * @param h
59 * @param outputFile
60 * @param verifySize
61 * @return
62 * @throws IOException
63 /
64 public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException{
65 String verifyCode = generateVerifyCode(verifySize);
66 outputImage(w, h, outputFile, verifyCode);
67 return verifyCode;
68 }
69
70 /*
71 * 输出随机验证码图片流,并返回验证码值
72 * @param w
73 * @param h
74 * @param os
75 * @param verifySize
76 * @return
77 * @throws IOException
78 /
79 public static String outputVerifyImage(int w, int h, OutputStream os, int verifySize) throws IOException{
80 String verifyCode = generateVerifyCode(verifySize);
81 outputImage(w, h, os, verifyCode);
82 return verifyCode;
83 }
84
85 /*
86 * 生成指定验证码图像文件
87 * @param w
88 * @param h
89 * @param outputFile
90 * @param code
91 * @throws IOException
92 /
93 public static void outputImage(int w, int h, File outputFile, String code) throws IOException{
94 if(outputFile == null){
95 return;
96 }
97 File dir = outputFile.getParentFile();
98 if(!dir.exists()){
99 dir.mkdirs();
100 }
101 try{
102 outputFile.createNewFile();
103 FileOutputStream fos = new FileOutputStream(outputFile);
104 outputImage(w, h, fos, code);
105 fos.close();
106 } catch(IOException e){
107 throw e;
108 }
109 }
110
111 /*
112 * 输出指定验证码图片流
113 * @param w
114 * @param h
115 * @param os
116 * @param code
117 * @throws IOException
118 */
119 public static void outputImage(int w, int h, OutputStream os, String code) throws IOException{
120 int verifySize = code.length();
121 BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
122 Random rand = new Random();
123 Graphics2D g2 = image.createGraphics();
124 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
125 Color[] colors = new Color[5];
126 Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN,
127 Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,
128 Color.PINK, Color.YELLOW };
129 float[] fractions = new float[colors.length];
130 for(int i = 0; i < colors.length; i++){
131 colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];
132 fractions[i] = rand.nextFloat();
133 }
134 Arrays.sort(fractions);
135
136 g2.setColor(Color.GRAY);// 设置边框色
137 g2.fillRect(0, 0, w, h);
138
139 Color c = getRandColor(200, 250);
140 g2.setColor©;// 设置背景色
141 g2.fillRect(0, 2, w, h-4);
142
143 //绘制干扰线
144 Random random = new Random();
145 g2.setColor(getRandColor(160, 200));// 设置线条的颜色
146 for (int i = 0; i < 20; i++) {
147 int x = random.nextInt(w - 1);
148 int y = random.nextInt(h - 1);
149 int xl = random.nextInt(6) + 1;
150 int yl = random.nextInt(12) + 1;
151 g2.drawLine(x, y, x + xl + 40, y + yl + 20);
152 }
153
154 // 添加噪点
155 float yawpRate = 0.05f;// 噪声率
156 int area = (int) (yawpRate * w * h);
157 for (int i = 0; i < area; i++) {
158 int x = random.nextInt(w);
159 int y = random.nextInt(h);
160 int rgb = getRandomIntColor();
161 image.setRGB(x, y, rgb);
162 }
163
164 shear(g2, w, h, c);// 使图片扭曲
165
166 g2.setColor(getRandColor(100, 160));
167 int fontSize = h-4;
168 Font font = new Font(“Algerian”, Font.ITALIC, fontSize);
169 g2.setFont(font);
170 char[] chars = code.toCharArray();
171 for(int i = 0; i < verifySize; i++){
172 AffineTransform affine = new AffineTransform();
173 affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize/2, h/2);
174 g2.setTransform(affine);
175 g2.drawChars(chars, i, 1, ((w-10) / verifySize) * i + 5, h/2 + fontSize/2 - 10);
176 }
177
178 g2.dispose();
179 ImageIO.write(image, “png”, os);
180 }
181
182 private static Color getRandColor(int fc, int bc) {
183 if (fc > 255)
184 fc = 255;
185 if (bc > 255)
186 bc = 255;
187 int r = fc + random.nextInt(bc - fc);
188 int g = fc + random.nextInt(bc - fc);
189 int b = fc + random.nextInt(bc - fc);
190 return new Color(r, g, b);
191 }
192
193 private static int getRandomIntColor() {
194 int[] rgb = getRandomRgb();
195 int color = 0;
196 for (int c : rgb) {
197 color = color << 8;
198 color = color | c;
199 }
200 return color;
201 }
202
203 private static int[] getRandomRgb() {
204 int[] rgb = new int[3];
205 for (int i = 0; i < 3; i++) {
206 rgb[i] = random.nextInt(255);
207 }
208 return rgb;
209 }
210
211 private static void shear(Graphics g, int w1, int h1, Color color) {
212 shearX(g, w1, h1, color);
213 shearY(g, w1, h1, color);
214 }
215
216 private static void shearX(Graphics g, int w1, int h1, Color color) {
217
218 int period = random.nextInt(2);
219
220 boolean borderGap = true;
221 int frames = 1;
222 int phase = random.nextInt(2);
223
224 for (int i = 0; i < h1; i++) {
225 double d = (double) (period >> 1)
226 * Math.sin((double) i / (double) period
227 + (6.2831853071795862D * (double) phase)
228 / (double) frames);
229 g.copyArea(0, i, w1, 1, (int) d, 0);
230 if (borderGap) {
231 g.setColor(color);
232 g.drawLine((int) d, i, 0, i);
233 g.drawLine((int) d + w1, i, w1, i);
234 }
235 }
236
237 }
238
239 private static void shearY(Graphics g, int w1, int h1, Color color) {
240
241 int period = random.nextInt(40) + 10; // 50;
242
243 boolean borderGap = true;
244 int frames = 20;
245 int phase = 7;
246 for (int i = 0; i < w1; i++) {
247 double d = (double) (period >> 1)
248 * Math.sin((double) i / (double) period
249 + (6.2831853071795862D * (double) phase)
250 / (double) frames);
251 g.copyArea(i, 0, 1, h1, 0, (int) d);
252 if (borderGap) {
253 g.setColor(color);
254 g.drawLine(i, (int) d, i, 0);
255 g.drawLine(i, (int) d + h1, i, h1);
256 }
257
258 }
259 }
260 public static void main(String[] args) throws IOException{
261 File dir = new File(“C:/Users/H__D/Desktop/”);
262 int w = 200, h = 80;
263 String verifyCode = generateVerifyCode(4);
264 File file = new File(dir, verifyCode + “.jpg”);
265 outputImage(w, h, file, verifyCode);
266 }
267 }使用图形验证码 1、使用流程
2、服务器端生成验证码servlet 1 package com.servlet;
2
3 import java.io.IOException;
4
5 import javax.servlet.ServletException;
6 import javax.servlet.http.HttpServlet;
7 import javax.servlet.http.HttpServletRequest;
8 import javax.servlet.http.HttpServletResponse;
9
10 import com.util.VerifyCodeUtils;
11
12
13 public class CreateCodeServlet extends HttpServlet {
14
15
16 @Override
17 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
18 resp.setHeader(“Pragma”, “No-cache”);
19 resp.setHeader(“Cache-Control”, “no-cache”);
20 resp.setDateHeader(“Expires”, 0);
21 resp.setContentType(“image/jpeg”);
22
23 //生成随机字串
24 String verifyCode = VerifyCodeUtils.generateVerifyCode(4);
25 //存入会话session
26 req.getSession().setAttribute(“CODE”, verifyCode.toLowerCase());
27
28 //生成图片
29 int width = 100;//宽
30 int height = 40;//高
31 VerifyCodeUtils.outputImage(width, height, resp.getOutputStream(), verifyCode);
32
33 }
34
35 @Override
36 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
37 // TODO Auto-generated method stub
38 doGet(req, resp);
39 }
40 }
3、服务器端验证验证码servlet 1 package com.servlet;
2
3 import java.io.IOException;
4
5 import javax.servlet.ServletException;
6 import javax.servlet.http.HttpServlet;
7 import javax.servlet.http.HttpServletRequest;
8 import javax.servlet.http.HttpServletResponse;
9
10 import com.util.VerifyCodeUtils;
11
12
13 public class VerifyCodeServlet extends HttpServlet {
14
15
16 @Override
17 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
18
19 String code = req.getParameter(“code”);
20 String key = (String) req.getSession().getAttribute(“CODE”);
21 if(code != null && code.equalsIgnoreCase(key)){
22 req.getSession().removeAttribute(“CODE”);
23 resp.getWriter().println(true);
24 }else{
25 resp.getWriter().println(false);
26 }
27 }
28
29 @Override
30 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
31 // TODO Auto-generated method stub
32 super.doGet(req, resp);
33 }
34 }
4、servet的注册,web.xml文件 1 <?xml version="1.0" encoding="UTF-8"?>
2
3 test-captcha
4
5
6
7 CreateCodeServlet
8 com.servlet.CreateCodeServlet
9
10
11 CreateCodeServlet
12 /createCode
13
14
15
16 VerifyCodeServlet
17 com.servlet.VerifyCodeServlet
18
19
20 VerifyCodeServlet
21 /verifyCode
22
23
24
25
26 index.jsp
27
28
5、前端html文件 1 <%@ page language=“java” contentType=“text/html; charset=UTF-8”
2 pageEncoding=“UTF-8”%>
3
4
5
6
7
8
9
10
测试验证码:
11 请输入验证码:
12 提交
13
42
43 6、使用浏览器打开页面访问,效果图如下:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/6a4430d7bbaece560b2cce27dcac3d86.gif#pic_center)