Java Web开发过程中登陆模块的验证码的实现方式总结
转载 2016-05-25 作者:死神的丧钟 我要评论
Java的SSH三大Web开发框架中,对于验证码这一基本功能的处理都比较得心应手,接下来我们就来看看整理出的Java Web开发过程中登陆模块的验证码的实现方式总结:
验证码及它的作用
验证码为全自动区分计算机和人类的图灵测试的缩写,是一种区分用户是计算机的公共全自动程序,这个问题可以由计算机生成并评判,但是必须只有人类才能解答.可以防止恶意破解密码、刷票、论坛灌水、有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登录。
图文验证码的原理
在servlet中随机生成一个指定位置的验证码,一般为四位,然后把该验证码保存到session中.在通过Java的绘图类以图片的形式输出该验证码。为了增加验证码的安全级别,可以输出图片的同时输出干扰线,最后在用户提交数据的时候,在服务器端将用户提交的验证码和Session保存的验证码进行比较。
实现方式总结
1 验证码生成类RandomCode
RandomCode是一个生成验证码的工具类,支持英文和数字验证码,验证码包括英文大小写和数组,其中英文i、o和数字0、1因为容易产生混淆,不包括在生成验证码中。RandomCode支持输出jpg/bmp/png/gif图片格式的验证码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
|
/**
* RandomCode验证码可以通过静态方法和实例方法生成。
*
* 静态方法:
*
* //生成长度为4的随机验证码
* String code = RandomCode.randomString(4);
*
* //把验证码图片输入到response输出流中
* //图片格式jpg
* OutputStream os = response.getOutputStream();
* RandomCode.write(code, 120, 30, os, "jpg");
*
* 实例方法:
*
* //实例化验证码类
* RandomCode rc = new RandomCode(4);
*
* //把验证码图片输入到response输出流中
* //图片格式jpg
* OutputStream os = response.getOutputStream();
* rc.write(120, 30, os, "jpg");
*
* //获取验证码字符串
* String code = rc.getCode();
*
*/
public
class
RandomCode {
/**
* 随机验证码字符
*/
private
static
String base =
"abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789"
;
/**
* 随机验证码长度
*/
private
int
length =
4
;
/**
* 验证码字符串
*/
private
String code;
/**
* 4位随机验证码
*/
public
RandomCode(){
this
.code = RandomCode.randomString(
this
.length);
}
public
RandomCode(
int
length){
if
(length >
0
){
this
.length = length;
}
this
.code = RandomCode.randomString(
this
.length);
}
/**
* 生成验证码图片
* @param width 图片宽度
* @param height 图片高度
* @return
*/
public
BufferedImage toImage(
int
width,
int
height){
return
RandomCode.toImage(
this
.code, width, height);
}
/**
* 输出验证码图片,默认图片格式jpeg
* @param width
* @param height
* @param os
* @throws IOException
*/
public
void
write(
int
width,
int
height, OutputStream os)
throws
IOException{
RandomCode.write(code, width, height, os,
"jpeg"
);
}
/**
* 输出验证码图片
* @param width
* @param height
* @param os
* @param format 图片格式,支持jpg/jpeg/bmp/gif/png
* @throws IOException
*/
public
void
write(
int
width,
int
height, OutputStream os, String format)
throws
IOException{
RandomCode.write(code, width, height, os, format);
}
public
int
getLength() {
return
length;
}
public
String getCode() {
return
code;
}
/**
* 静态方法
* 生成随机字符串
* @param length 字符串长度
* @return 随机字符串
*/
public
static
String randomString(
int
length){
Random random =
new
Random();
StringBuffer sb =
new
StringBuffer();
for
(
int
i =
0
; i < length; i++){
sb.append(base.charAt(random.nextInt(base.length())));
}
return
sb.toString();
}
/**
* 静态方法
* 输出验证码图片
* @param code 验证码字符串
* @param width 图片宽度
* @param height 图片高度
* @param os 图片输出流
* @param format 图片格式,支持jpg/jpeg/bmp/gif/png
* @throws IOException
*/
public
static
void
write(String code,
int
width,
int
height, OutputStream os, String format)
throws
IOException{
BufferedImage image = toImage(code, width, height);
ImageIO.write(image, format, os);
}
/**
* 静态方法
* 输出验证码图片,默认图片格式jpeg
* @param code 验证码字符串
* @param width 图片宽度
* @param height 图片高度
* @param os 图片输出流
* @throws IOException
*/
public
static
void
write(String code,
int
width,
int
height, OutputStream os)
throws
IOException{
write(code, width, height, os,
"jpeg"
);
}
/**
* 静态方法
* 字符串转成验证码图片
* @param code 验证码字符串
* @param width 验证码图片宽度,单位像素
* @param height 验证码图片高度,单位像素
* @return
*/
public
static
BufferedImage toImage(String code,
int
width,
int
height){
//字体大小
int
fontSize = (
int
)Math.ceil(height *
0.9
);
if
(fontSize <
20
){
fontSize =
20
;
}
//字体在Y坐标上的位置
int
positionY = (
int
)Math.ceil(height *
0.8
);
int
lenCode = code.length();
//计算字体宽度
int
fontWidth = width / (lenCode +
2
);
BufferedImage image =
new
BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
Graphics g = image.getGraphics();
//图片背景随机颜色
g.setColor(randomColor(
new
Random(),
200
,
250
));
g.fillRect(
0
,
0
, width, height);
//设置字体
g.setFont(
new
Font(
"Times New Roman"
, Font.BOLD, fontSize));
//在图片上画纵横交错的线,达到混淆效果
drawLines(g, width, height);
//在图片上画验证码
drawString(g, code, fontWidth, positionY);
g.dispose();
return
image;
}
/**
* 静态方法
* 在图片上话位子
* @param g
* @param code 验证码字符串
* @param fontWidth 字体宽度
* @param positionY 字体Y坐标
*/
private
static
void
drawString(Graphics g, String code,
int
fontWidth,
int
positionY){
int
len = code.length();
Random random =
new
Random();
for
(
int
i =
0
; i < len; i++){
g.setColor(randomColor(random));
g.drawString(String.valueOf(code.charAt(i)), (i +
1
) * fontWidth, positionY);
}
}
private
static
Color randomColor(Random random){
int
r = random.nextInt(
255
);
int
g = random.nextInt(
255
);
int
b = random.nextInt(
255
);
return
new
Color(r, g, b);
}
private
static
Color randomColor(Random random,
int
fc,
int
bc){
if
(fc >
255
){
fc =
255
;
}
if
(bc >
255
){
bc =
255
;
}
int
diff = bc-fc;
int
r = fc + random.nextInt(diff);
int
g = fc + random.nextInt(diff);
int
b = fc + random.nextInt(diff);
return
new
Color(r,g,b);
}
/**
* 静态方法
* 画纵横交错的线
* @param g
* @param width 验证码图片宽度
* @param height 验证码图片高度
*/
private
static
void
drawLines(Graphics g,
int
width,
int
height){
Random random =
new
Random();
//线的数量
int
count = ((
int
)(Math.ceil(random.nextDouble() *
100
))) +
100
;
for
(
int
i =
0
; i < count; i++){
int
fc =
160
+ (
int
)Math.ceil(random.nextDouble() *
40
);
int
bc =
200
+ (
int
)Math.ceil(random.nextDouble() *
55
);
g.setColor(randomColor(random, fc, bc));
int
x = random.nextInt(width);
int
y = random.nextInt(height);
int
xl = random.nextInt(width /
5
);
int
yl = random.nextInt(height /
5
);
g.drawLine(x, y, x + xl, y + yl);
}
}
}
|
2 Servlet返回验证码
请求路径http://<网站路径>/random/code/servlet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
@WebServlet
(
"/random/code/servlet"
)
public
class
RandomCodeServlet
extends
HttpServlet {
private
static
final
long
serialVersionUID = 1L;
protected
void
service(HttpServletRequest request, HttpServletResponse response)
throws
ServletException, IOException {
// 验证码图片宽度,单位像素
int
width =
120
;
// 验证码图片高度,单位像素
int
height =
30
;
// 验证码图片格式
String format =
"png"
;
// 验证码字符长度
int
len =
4
;
// 设置图片格式
response.setContentType(
"image/"
+ format);
// 禁止浏览器缓存图片
response.setHeader(
"Pragma"
,
"no-cache"
);
response.setHeader(
"Cache-Control"
,
"no-cache"
);
response.setDateHeader(
"Expires"
,
0
);
String code = RandomCode.randomString(len);
// 把图片输出到response输出流
RandomCode.write(code, width, height, response.getOutputStream(), format);
}
}
|
3 Strust2返回验证码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
public
class
RandomCodeAction
extends
ActionSupport {
private
static
final
long
serialVersionUID = -7515645222798283236L;
/**
* 获取验证码
*/
public
void
generateCode() {
HttpServletResponse response = ServletActionContext.getResponse();
// 验证码图片宽度,单位像素
int
width =
120
;
// 验证码图片高度,单位像素
int
height =
30
;
// 验证码图片格式
String format =
"png"
;
// 验证码字符长度
int
len =
4
;
// 设置图片格式
response.setContentType(
"image/"
+ format);
// 禁止浏览器缓存图片
response.setHeader(
"Pragma"
,
"no-cache"
);
response.setHeader(
"Cache-Control"
,
"no-cache"
);
response.setDateHeader(
"Expires"
,
0
);
String code = RandomCode.randomString(len);
// 把图片输出到response输出流
try
{
RandomCode.write(code, width, height, response.getOutputStream(), format);
}
catch
(IOException e) {
e.printStackTrace();
}
}
}
|
Struts2的验证码配置
1
2
3
|
<
package
name
=
"pkg-random-code"
namespace
=
"/"
extends
=
"struts-default"
>
<
action
name
=
"randomCode_*"
method
=
"{1}"
class
=
"com.rhui.web.action.RandomCodeAction"
></
action
>
</
package
>
|
请求路径http://<网站路径>/randomCode_generateCode.do
4 SpringMVC返回验证码
请求路径http://<网站路径>/random/code/generate.do
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
package
com.rhui.web.controller;
import
java.io.IOException;
import
javax.servlet.http.HttpServletResponse;
import
org.springframework.stereotype.Controller;
import
org.springframework.web.bind.annotation.RequestMapping;
import
com.rhui.util.RandomCode;
@Controller
@RequestMapping
(
"/random/code"
)
public
class
RandomCodeController {
@RequestMapping
(
"/generate.do"
)
public
void
generateCode(HttpServletResponse response) {
// 验证码图片宽度,单位像素
int
width =
120
;
// 验证码图片高度,单位像素
int
height =
30
;
// 验证码图片格式
String format =
"png"
;
// 验证码字符长度
int
len =
4
;
// 设置图片格式
response.setContentType(
"image/"
+ format);
// 禁止浏览器缓存图片
response.setHeader(
"Pragma"
,
"no-cache"
);
response.setHeader(
"Cache-Control"
,
"no-cache"
);
response.setDateHeader(
"Expires"
,
0
);
String code = RandomCode.randomString(len);
// 把图片输出到response输出流
try
{
RandomCode.write(code, width, height, response.getOutputStream(), format);
}
catch
(IOException e) {
e.printStackTrace();
}
}
}
|