1. 使用Servlet实现验证码
首先创建工程,实现jsp代码:
<script type="text/javascript">
function reloadCode() {
var time = new Date().getTime();
document.getElementById("image_code").src = "<%=path%>/servlet/ImageServlet?d="
+ time;
}
</script>
</head>
<body>
验证码:
<input type="text" name="check_code">
<img id="image_code" alt="验证码"
src="<%=request.getContextPath()%>/servlet/ImageServlet">
<a href="javascript:reloadCode();">看不清楚</a>
<br>
</body>
重新加载的函数有一个d的参数,这是为了防止传相同的地址浏览器无法刷新。可以看出我们的img标签使用的是Servlet来填充的,接下来是我们的ImageServlet:
<span style="white-space:pre"> </span>protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
BufferedImage bi = new BufferedImage(68, 22, BufferedImage.TYPE_INT_RGB);
Graphics g = bi.getGraphics();
Color c = new Color(200, 150, 255);
g.setColor(c);
g.fillRect(0, 0, 68, 22);
// 生成26个英文字母的数组
char[] ch = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
// 随机获取4个字符
Random r = new Random();
int len = ch.length;
int index = 0;
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 4; i++) {
index = r.nextInt(len);
g.setColor(new Color(r.nextInt(88), r.nextInt(188), r.nextInt(255)));
g.drawString(ch[index] + "", i * 15 + 3, 18);
sb.append(ch[index]);
}
req.getSession().setAttribute("check_code", sb.toString());
ImageIO.write(bi, "JPG", resp.getOutputStream());
}
只用重写Servlet的doGet方法就可以了。接下来是验证验证码:
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
String checkCode = (String) request.getSession().getAttribute(
"check_code");
String userCode = request.getParameter("check_code");
PrintWriter out = response.getWriter();
if (checkCode.equals(userCode)) {
out.print("验证码输入正确");
} else {
out.print("验证码输入错误");
}
out.close();
}
如果不想区分大小写的话,在获取userCode的时候可以统一转换成大写即可。
2. 使用Jcaptcha组件实现验证码
Jcaptcha是一个用来生成图形验证码的Java开源组件,使用起来也是非常的简单方便。常常与Spring组合使用,可以产生多种形式的验证码。
Jcaptcha是一个开源的组件,
先是jsp代码:
<form action="submit.action" method="post">
<img src="jcaptcha.jpg" /> <input type="text" name="japtcha" value="" />
<input type="submit"/>
</form>
然后需要导入几个这个开源的jar包,后面工程里都有。然后配置web.xml
<web-app>
<display-name>Simple Image Captcha Servlet Sample</display-name>
<servlet>
<servlet-name>jcaptcha</servlet-name>
<servlet-class>com.octo.captcha.module.servlet.image.SimpleImageCaptchaServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>submit</servlet-name>
<servlet-class>com.octo.captcha.module.servlet.image.sample.SubmitActionServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>jcaptcha</servlet-name>
<url-pattern>/jcaptcha.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>submit</servlet-name>
<url-pattern>/submit.action</url-pattern>
</servlet-mapping>
</web-app>
最后是提交servlet的代码:
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
String userCaptchaResponse = request.getParameter("japtcha");
boolean captchaPassed = SimpleImageCaptchaServlet.validateResponse(
request, userCaptchaResponse);
if (captchaPassed)
response.getWriter().write("captcha passed");
else {
response.getWriter().write("captcha failed");
}
response.getWriter().write("<a href='index.jsp'>Try again</a>");
}
也是很简单。
3. 使用Kaptcha实现验证码
Kaptcha也是一个非常实用的验证码生成工具,有了它,你可以生成各种样式的验证码,因为它是可配置的。
(1). 首先是字母数组组合验证
先导入包kaptcha-2.3.jar,index.jsp:
<form action="check.jsp">
<img src="randomcode.jpg"> <input type="text" name="r">
<input type="submit" name="s"> <br>
</form>
在web.xml重配置:
<servlet>
<servlet-name>kaptcha</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>kaptcha</servlet-name>
<url-pattern>/randomcode.jpg</url-pattern>
</servlet-mapping>
检测验证码是否正确的check.jsp:
<%
// 检查是否是正确的验证码
String k = (String) session
.getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
String str = request.getParameter("r");
if (k.equals(str)) {
out.print("true");
}
out.print(k + "---" + str);
%>
(2). Kaptcha的详细配置在web.xml中的<servlet>标签的<init-param>标签内,可以配置多个设置:
1). 是否加入边框:
<description>图片边框,合法值:yes,no</description>
<param-name>kaptcha.border</param-name>
<param-value>yes</param-value>
2). 设置边框颜色:
<description>边框颜色,合法值:white、black、blue等</description>
<param-name>kaptcha.border.color</param-name>
<param-value>black</param-value>
3). 边框厚度:
<description>边框厚度,合法值:0等</description>
<param-name>kaptcha.border.thickness</param-name>
<param-value>1</param-value>
3). 图片宽度:
<description>图片宽度</description>
<param-name>kaptcha.image.width</param-name>
<param-value>100</param-value>
4). 图片高度:
<description>图片高度</description>
<param-name>kaptcha.image.height</param-name>
<param-value>50</param-value>
5). 图片实现类:
<description>图片实现类</description>
<param-name>kaptcha.producer.impl</param-name>
<param-value>com.google.code.kaptcha.implDefaultKaptcha</param-value>
6). 文本实现类:
<description>文本实现类</description>
<param-name>kaptcha.textproducer.impl</param-name>
<param-value>com.google.code.kaptcha.text.implDefaultTextCreator</param-value>
7). 验证码配置:
<description>文本集合,验证码值从此集合中获取</description>
<param-name>kaptcha.textproducer.char.string</param-name>
<param-value>abcde234567gfmnopq</param-value>
8). 验证码长度:
<description>验证码长度 5</description>
<param-name>kaptcha.textproducer.char.length</param-name>
<param-value>2</param-value>
9). 验证码字体:
<description>字体Arial,Courier</description>
<param-name>kaptcha.textproducer.font.names</param-name>
<param-value>Arial, Courier</param-value>
10). 验证码字体大小:
<description>字体大小40px</description>
<param-name>kaptcha.textproducer.font.size</param-name>
<param-value>40</param-value>
11). 验证码字体颜色:
<description>字体颜色,合法值:white、black等</description>
<param-name>kaptcha.textproducer.font.color</param-name>
<param-value>black</param-value>
12). 验证码文字间隔:
<description>文字间隔</description>
<param-name>kaptcha.textproducer.char.space</param-name>
<param-value>2</param-value>
13). 验证码干扰实现类:
<description>干扰实现类</description>
<param-name>kaptcha.noise.impl</param-name>
<param-value>com.google.code.kaptcha.impl.DefaultNoise</param-value>
14). 干扰颜色:
<description>干扰颜色,合法值:r, g, b或者black等</description>
<param-name>kaptcha.noise.color</param-name>
<param-value>black</param-value>
15). 验证码图片样式:
<description>图片样式:水纹com.google.code.kaptcha.impl.WaterRipple、鱼眼com.google.code.kaptcha.impl.FishEyeGimpy、阴影com.google.code.kaptcha.impl.ShadowGimpy等</description>
<param-name>kaptcha.obscurificator.impl</param-name>
<param-value>com.google.code.kaptcha.impl.WaterRipple</param-value>
16). 背景实现类:
<description>背景实现类</description>
<param-name>kaptcha.background.impl</param-name>
<param-value>com.google.code.kaptcha.impl.DefaultBackground</param-value>
17). 背景颜色渐变-开始颜色:
<description>颜色渐变-开始颜色</description>
<param-name>kaptcha.background.clear.from</param-name>
<param-value>green</param-value>
18). 背景颜色渐变-结束颜色:
<description>颜色渐变-结束颜色</description>
<param-name>kaptcha.background.clear.to</param-name>
<param-value>white</param-value>
19). 文字渲染器:
<description>文字渲染器</description>
<param-name>kaptcha.word.impl</param-name>
<param-value>com.google.code.kaptcha.text.impl.DefaultWordRenderer</param-value>
20). 验证码在session中存放验证码的key键配置:
<description>session中存放验证码的key键</description>
<param-name>kaptcha.session.key</param-name>
<param-value>KAPTCHA_SESSION_KEY</param-value>
(3). 中文验证码的实现
首先是我们生成中文的类:
public class ChineseText extends Configurable implements TextProducer {
public String getText() {
int length = getConfig().getTextProducerCharLength();
String finalWord = "", firstWord = "";
int tempInt = 0;
String[] array = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"a", "b", "c", "d", "e", "f" };
Random rand = new Random();
for (int i = 0; i < length; i++) {
switch (rand.nextInt(array.length)) {
case 1:
tempInt = rand.nextInt(26) + 65;
firstWord = String.valueOf((char) tempInt);
break;
case 2:
int r1,
r2,
r3,
r4;
String strH,
strL;// high&low
r1 = rand.nextInt(3) + 11; // 前闭后开[11,14)
if (r1 == 13) {
r2 = rand.nextInt(7);
} else {
r2 = rand.nextInt(16);
}
r3 = rand.nextInt(6) + 10;
if (r3 == 10) {
r4 = rand.nextInt(15) + 1;
} else if (r3 == 15) {
r4 = rand.nextInt(15);
} else {
r4 = rand.nextInt(16);
}
strH = array[r1] + array[r2];
strL = array[r3] + array[r4];
byte[] bytes = new byte[2];
bytes[0] = (byte) (Integer.parseInt(strH, 16));
bytes[1] = (byte) (Integer.parseInt(strL, 16));
firstWord = new String(bytes);
break;
default:
tempInt = rand.nextInt(10) + 48;
firstWord = String.valueOf((char) tempInt);
break;
}
finalWord += firstWord;
}
return finalWord;
}
}
需要继承Configurable类,实现TextProducer接口。然后在web.xml中配置: <init-param>
<description>文本实现类</description>
<param-name>kaptcha.textproducer.impl</param-name>
<param-value>com.thr.text.ChineseText</param-value>
</init-param>
注意我们这里要指定类的全名。如果当输入中文检测出现乱码时,修改check.jsp:
<%
// 检查是否是正确的验证码
String k = (String) session
.getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
String str = request.getParameter("r");
str = new String(str.getBytes("ISO-8859-1"), "UTF-8");
if (k.equals(str)) {
out.print("true");
}
out.print(k + "---" + str);
%>
(4). 算式验证码的实现
我们要写一个Servlet来实现:
public class KaptchaServlet extends HttpServlet implements Servlet {
private Properties props;
private Producer kaptchaProducer;
private String sessionKeyValue;
public KaptchaServlet() {
this.props = new Properties();
this.kaptchaProducer = null;
this.sessionKeyValue = null;
}
public void init(ServletConfig conf) throws ServletException {
super.init(conf);
ImageIO.setUseCache(false);
Enumeration initParams = conf.getInitParameterNames();
while (initParams.hasMoreElements()) {
String key = (String) initParams.nextElement();
String value = conf.getInitParameter(key);
this.props.put(key, value);
}
Config config = new Config(this.props);
this.kaptchaProducer = config.getProducerImpl();
this.sessionKeyValue = config.getSessionKey();
}
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setDateHeader("Expires", 0L);
resp.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
resp.addHeader("Cache-Control", "post-check=0, pre-check=0");
resp.setHeader("Pragma", "no-cache");
resp.setContentType("image/jpeg");
String capText = this.kaptchaProducer.createText();
String s1 = capText.substring(0, 1);
String s2 = capText.substring(1, 2);
int r = Integer.valueOf(s1).intValue() + Integer.valueOf(s2).intValue();
req.getSession().setAttribute(this.sessionKeyValue, String.valueOf(r));
BufferedImage bi = this.kaptchaProducer.createImage(s1 + "+" + s2
+ "=?");
ServletOutputStream out = resp.getOutputStream();
ImageIO.write(bi, "jpg", out);
try {
out.flush();
} finally {
out.close();
}
}
}
然后在web.xml中替换掉我们之前使用的servlet即可。