验证码是一种区别用户是计算机还是人的公共全自动程序,他被用于防止恶意破解密码、刷票、论坛灌水,防止黑客通过暴力破解方式不断地登录,应用于银行、社区、论坛、投票系统等等。
废话不多说我们来看看我已知的用Java实现验证码的四种方式。
方法一:
第一种方法是我最先想到的,也是实现逻辑最简单的,但效率、安全性极其不高。
具体操作就是:1、用photoshop制作出验证码图片,矩形图片上可有必要的英文字母、数字或中文(如上)
2、将图片显示在swing控件中或是jsp页面中
3、在代码中为每张图片匹配上相应的验证码字符串
4、在提交时获取组件或文本框中的字符串与每张图片的字符串用equals()方法进行比较
缺憾就是制作验证码图片的过程太费时,实现方法极low,极不推荐这样实现,下面的方法将越来越高效美观相对安全。
方法二:
这里讲Java Web,Servlet下的验证码实现,实现起来逻辑还是很清晰的。
省去较简单的实现代码,我们先从前台关键代码说起:
当我们点击"看不清"时,验证码图片会进行一个刷新,会调用一个js函数用于重新设置图片路径来更换图片,请看下面代码,代码中<%=request.getContextPath()%>是为了解决相对路径的问题,可返回站点的根路径,而/servlet/ImageServlet是一个整体,指向的就是ImageServlet这个servlet,为什么要在之前加个/servlet呢,因为我们在web.xml中做了配置映射,可理解为换了个更长的名称。接着看下面js函数,可能有些人会有疑问,为什么获取一个当前时间然后加在路径最后呢,其实这是为了解决浏览器缓存的问题,就是当触发了ImageServlet后虽然验证码图片换了但缓存还没变显示出来的验证码图片不变的问题,借助每时每刻时间不同可以让浏览器缓存失效。
1
2
3
4
5
6
|
<script type=
"text/javascript"
>
function reloadCode(){
var time =
new
Date().getTime();
document.getElementById(
"imagecode"
).src=
"<%=request.getContextPath() %>/servlet/ImageServlet?d="
+time;
}
</script>
|
下面是web.xml中的关键配置信息:
1
2
3
4
5
6
|
<script type=
"text/javascript"
>
function
reloadCode(){
var
time =
new
Date().getTime();
document.getElementById(
"imagecode"
).src=
"<%=request.getContextPath() %>/servlet/ImageServlet?d="
+time;
}
</script>
|
然后我们看关键的ImageServlet是怎么生成图片的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<servlet>
<servlet-name>ImageServlet</servlet-name>
<servlet-
class
>com.muke.ImageServlet</servlet-
class
>
</servlet>
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-
class
>com.muke.LoginServlet</servlet-
class
>
</servlet>
<servlet-mapping>
<servlet-name>ImageServlet</servlet-name>
<url-pattern>/servlet/ImageServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/servlet/LoginServlet</url-pattern>
</servlet-mapping>
|
如果要更生动的描述这种验证码是怎么样来实现的,那么就一个字“画”,听上去和第一种方法类似,还是比较low,但是用代码来自动“画”出验证码效率绝对翻了无数倍。我们来看上述代码,首先实例化了一个BufferedImage对象bi,bi是用来画出那张验证码图片的,然后用bi得到一支画笔g,用g画出了实体的矩形背景,接着用简单的逻辑通过画笔g调用Java中常用的drawString()方法在矩形上画出验证码字符,同时将字符串依次加入StringBuffer可变字符串对象中,最后存入jsp内置对象session中以便提交验证码后的比对,为了显示出验证码,我们还需将生成验证码图片以某种图片格式写入ImageIO流。
下面LoginServlet中可以看出,获取刚刚ImageServlet存入session的字符串就可以进行与验证码提交框中字符串的比对了,可以把字符串都变为小写或大写做一个忽略大小写的处理。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public
class
ImageServlet
extends
HttpServlet {
public
void
doGet(HttpServletRequest request, HttpServletResponse response)
throws
IOException{
BufferedImage bi =
new
BufferedImage(,,BufferedImage.TYPE_INT_RGB);
Graphics g = bi.getGraphics();
Color c =
new
Color(,,);
g.setColor(c);
g.fillRect(, , , );
char
[] ch =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
.toCharArray();
Random r =
new
Random();
int
len=ch.length,index;
StringBuffer sb =
new
StringBuffer();
for
(
int
i=; i<; i++){
index = r.nextInt(len);
g.setColor(
new
Color(r.nextInt(),r.nextInt(),r.nextInt()));
g.drawString(ch[index]+
""
, (i*)+, );
sb.append(ch[index]);
}
request.getSession().setAttribute(
"piccode"
, sb.toString());
ImageIO.write(bi,
"JPG"
, response.getOutputStream());
}
}
|
下面是实现图例: