这种验证方式本身是在后台进行验证的,但是给用户的体验感觉很差,因为每次都需要整个表单提交,当验证码输入错误后返回原页面,原来填写的数据全部刷新清空了。这时候很自然地就想到用JavaScript在前台进行验证,经过简单地改造(这个代码就不用贴出来了吧),启动服务进行测试,这时候发现一个很奇怪的问题,我得到session中的验证码总是前一次的,根本不能进行正确的验证!
产生这种结果的原因是:我们一般使用
1.
<
img
src
=
'image.jsp'
/>
标签来导入验证图片,这就要一个先后加载次序了,我们先访问注册页面,而后通过上面的img导入的加载图片验证码页面,而我们的session里存放是在image页面,这就注定了session里面保存总是上次生成的数字或字符,无法获取当前生成的数值。
既然这样,我们何不在register.jsp页面就生成这个随机的验证字符串呢,在用一个hidden保存它的值,然后将它存入session,在image.jsp中直接生成这个字符串的图片验证码,返回register.jsp,然后用js判断hidden中的值是否和输入的值相同,以达到验证的目的。
具体实现代码如下:
1.regster.jsp页面 --随机生成数字并放入session:
01.
<%
02.
//生成随机类
03.
Random random = new Random();
04.
String sRand = "";
05.
for (int i = 0; i <
4
; i++) {
06.
String
rand
=
String
.valueOf(random.nextInt(10));
07.
sRand += rand;
08.
}
09.
session.setAttribute("code",sRand);//放入session中
10.
%>
2.image.jsp页面---获取session中的code,写入生成的图片中
01.
<%@ page contentType="image/JPEG"
02.
import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*,java.awt.Color"
03.
pageEncoding="GBK"%><%!Color getRandColor(int fc, int bc) {//给定范围获得随机颜色
04.
Random random = new Random();
05.
if (fc > 255)
06.
fc = 255;
07.
if (bc > 255)
08.
bc = 255;
09.
int r = fc + random.nextInt(bc - fc);
10.
int g = fc + random.nextInt(bc - fc);
11.
int b = fc + random.nextInt(bc - fc);
12.
return new Color(r, g, b);
13.
}%><%
14.
//设置页面不缓存
15.
response.setHeader("Pragma", "No-cache");
16.
response.setHeader("Cache-Control", "no-cache");
17.
response.setDateHeader("Expires", 0);
18.
19.
// 在内存中创建图象
20.
int width = 60, height = 20;
21.
BufferedImage image = new BufferedImage(width, height,
22.
BufferedImage.TYPE_INT_RGB);
23.
24.
// 获取图形上下文
25.
Graphics g = image.getGraphics();
26.
27.
//生成随机类
28.
Random random = new Random();
29.
30.
// 设定背景色
31.
g.setColor(getRandColor(200, 250));
32.
g.fillRect(0, 0, width, height);
33.
34.
//设定字体
35.
g.setFont(new Font("Times New Roman", Font.PLAIN, 18));
36.
37.
//画边框
38.
g.setColor(new Color(0,0,0));
39.
g.drawRect(0,0,width-1,height-1);
40.
41.
// 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到
42.
g.setColor(getRandColor(160, 200));
43.
for (int i = 0; i <
100
; i++) {
44.
int
x
=
random
.nextInt(width);
45.
int
y
=
random
.nextInt(height);
46.
int
xl
=
random
.nextInt(12);
47.
int
yl
=
random
.nextInt(12);
48.
g.drawLine(x, y, x + xl, y + yl);
49.
}
50.
51.
//获取session中的code,写入生成的图片中
52.
String code =(String)session.getAttribute("code");
53.
for(int
i
=
0
; i<code.length();i++){
54.
String
rand
=
code
.substring(i,i+1);
55.
// 将认证码显示到图象中
56.
g.setColor(new Color(20 + random.nextInt(110), 20 + random
57.
.nextInt(110), 20 + random.nextInt(110)));//调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
58.
g.drawString(rand, 13 * i + 6, 16);
59.
}
60.
61.
// 将认证码存入SESSION
62.
// session.setAttribute("code", sRand); //这是以前的做法,删除
63.
64.
// 图象生效
65.
g.dispose();
66.
67.
// 输出图象到页面
68.
ImageIO.write(image, "JPEG", response.getOutputStream());
69.
out.clear();
70.
out
=
pageContext
.pushBody();
71.
%>
3.register.jsp页面----设置隐藏域获取session值,和JS判断
1)设置隐藏域获取session值
1.
<
input
type
=
"hidden"
id
=
"code"
value
=
"<%=session.getAttribute("
code")%>"/>
2)JS判断 ----验证码输入框
1.
<
input
type
=
'text'
id
=
'image'
/>
1.
if
(document.getElementById(
'image'
).value != document.getElementById(
'code'
).value) {
2.
alert(
"您输入的验证码有误!"
);
3.
image.focus();
4.
return
false
;
5.
}