1 /**
2 *
3 */
4 package org.jeecgframework.web.system.servlet;
5
6 import org.jeecgframework.core.util.ResourceUtil;
7
8 import java.awt.Color;
9 import java.awt.Font;
10 import java.awt.Graphics2D;
11 import java.awt.image.BufferedImage;
12 import java.io.IOException;
13 import java.util.Random;
14
15 import javax.imageio.ImageIO;
16 import javax.servlet.ServletException;
17 import javax.servlet.http.HttpServlet;
18 import javax.servlet.http.HttpServletRequest;
19 import javax.servlet.http.HttpServletResponse;
20
21
22 /**
23 * 随机生成验证图片
24 *
25 *
26 */
27 public class RandCodeImageServlet extends HttpServlet {
28 private static final long serialVersionUID = -1257947018545327308L;
29 private static final String SESSION_KEY_OF_RAND_CODE = "randCode"; // todo 要统一常量
30 /**
31 *
32 */
33 private static final int count = 200;
34
35 /**
36 * 定义图形大小
37 */
38 private static final int width = 105;
39 /**
40 * 定义图形大小
41 */
42 private static final int height = 35;
43 // private Font mFont = new Font("Arial Black", Font.PLAIN, 15); //设置字体
44 /**
45 * 干扰线的长度=1.414*lineWidth
46 */
47 private static final int lineWidth = 2;
48
49 @Override
50 public void doGet(final HttpServletRequest request,
51 final HttpServletResponse response) throws ServletException,
52 IOException {
53 // 设置页面不缓存
54 response.setHeader("Pragma", "No-cache");
55 response.setHeader("Cache-Control", "no-cache");
56 response.setDateHeader("Expires", 0);
57 // response.setContentType("image/png");
58
59 // 在内存中创建图象
60 final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
61 // 获取图形上下文
62 final Graphics2D graphics = (Graphics2D) image.getGraphics();
63
64 // 设定背景颜色
65 graphics.setColor(Color.WHITE); // ---1
66 graphics.fillRect(0, 0, width, height);
67 // 设定边框颜色
68 // graphics.setColor(getRandColor(100, 200)); // ---2
69 graphics.drawRect(0, 0, width - 1, height - 1);
70
71 final Random random = new Random();
72 // 随机产生干扰线,使图象中的认证码不易被其它程序探测到
73 for (int i = 0; i < count; i++) {
74 graphics.setColor(getRandColor(150, 200)); // ---3
75
76 final int x = random.nextInt(width - lineWidth - 1) + 1; // 保证画在边框之内
77 final int y = random.nextInt(height - lineWidth - 1) + 1;
78 final int xl = random.nextInt(lineWidth);
79 final int yl = random.nextInt(lineWidth);
80 graphics.drawLine(x, y, x + xl, y + yl);
81 }
82
83 // 取随机产生的认证码(4位数字)
84 final String resultCode = exctractRandCode();
85 for (int i = 0; i < resultCode.length(); i++) {
86 // 将认证码显示到图象中,调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
87 // graphics.setColor(new Color(20 + random.nextInt(130), 20 + random
88 // .nextInt(130), 20 + random.nextInt(130)));
89
90 // 设置字体颜色
91 graphics.setColor(Color.BLACK);
92 // 设置字体样式
93 // graphics.setFont(new Font("Arial Black", Font.ITALIC, 18));
94 graphics.setFont(new Font("Times New Roman", Font.BOLD, 24));
95 // 设置字符,字符间距,上边距
96 graphics.drawString(String.valueOf(resultCode.charAt(i)), (23 * i) + 8, 26);
97 }
98
99 // 将认证码存入SESSION
100 request.getSession().setAttribute(SESSION_KEY_OF_RAND_CODE, resultCode);
101 // 图象生效
102 graphics.dispose();
103
104 // 输出图象到页面
105 ImageIO.write(image, "JPEG", response.getOutputStream());
106 }
107
108 @Override
109 public void doPost(final HttpServletRequest request,
110 final HttpServletResponse response) throws ServletException,
111 IOException {
112 doGet(request, response);
113 }
114
115 /**
116 * @return 随机码
117 */
118 private String exctractRandCode() {
119 final String randCodeType = "5";
120 int randCodeLength = Integer.parseInt("4");
121 if (randCodeType == null) {
122 return RandCodeImageEnum.NUMBER_CHAR.generateStr(randCodeLength);
123 } else {
124 switch (randCodeType.charAt(0)) {
125 case '1':
126 return RandCodeImageEnum.NUMBER_CHAR.generateStr(randCodeLength);
127 case '2':
128 return RandCodeImageEnum.LOWER_CHAR.generateStr(randCodeLength);
129 case '3':
130 return RandCodeImageEnum.UPPER_CHAR.generateStr(randCodeLength);
131 case '4':
132 return RandCodeImageEnum.LETTER_CHAR.generateStr(randCodeLength);
133 case '5':
134 return RandCodeImageEnum.ALL_CHAR.generateStr(randCodeLength);
135
136 default:
137 return RandCodeImageEnum.NUMBER_CHAR.generateStr(randCodeLength);
138 }
139 }
140 }
141
142 /**
143 * 描述:
144 *
145 * @param fc
146 * 描述:
147 * @param bc
148 * 描述:
149 *
150 * @return 描述:
151 */
152 private Color getRandColor(int fc, int bc) { // 取得给定范围随机颜色
153 final Random random = new Random();
154 if (fc > 255) {
155 fc = 255;
156 }
157 if (bc > 255) {
158 bc = 255;
159 }
160
161 final int r = fc + random.nextInt(bc - fc);
162 final int g = fc + random.nextInt(bc - fc);
163 final int b = fc + random.nextInt(bc - fc);
164
165 return new Color(r, g, b);
166 }
167 }
168
169 /**
170 * 验证码辅助类
171 *
172 */
173 enum RandCodeImageEnum {
174 /**
175 * 混合字符串
176 */
177 ALL_CHAR("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"),
178 /**
179 * 字符
180 */
181 LETTER_CHAR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"),
182 /**
183 * 小写字母
184 */
185 LOWER_CHAR("abcdefghijklmnopqrstuvwxyz"),
186 /**
187 * 数字
188 */
189 NUMBER_CHAR("0123456789"),
190 /**
191 * 大写字符
192 */
193 UPPER_CHAR("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
194 /**
195 * 待生成的字符串
196 */
197 private String charStr;
198
199 /**
200 * @param charStr
201 */
202 private RandCodeImageEnum(final String charStr) {
203 this.charStr = charStr;
204 }
205
206 /**
207 * 生产随机验证码
208 *
209 * @param codeLength
210 * 验证码的长度
211 * @return 验证码
212 */
213 public String generateStr(final int codeLength) {
214 final StringBuffer sb = new StringBuffer();
215 final Random random = new Random();
216 final String sourseStr = getCharStr();
217
218 for (int i = 0; i < codeLength; i++) {
219 sb.append(sourseStr.charAt(random.nextInt(sourseStr.length())));
220 }
221
222 return sb.toString();
223 }
224
225 /**
226 * @return the {@link #charStr}
227 */
228 public String getCharStr() {
229 return charStr;
230 }
231
232 }