【JavaWeb】(11)Java实现验证码制作

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即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值