Ajax Fancy Capcha

几天前看见JE上新闻上的Jquery插件中,有一个叫Ajax Fancy Captcha的验证码插件,虽然jcaptcha也还不错,但就因为一验证码莫明的多个组件出来,这并不是什么好事,更何况jcaptcha还依赖几个其它的组件。当然也有人说可以用recaptcha,虽然recaptcha没有用过,不过人家说了:reCAPTCHA is a Web service,我个人不太喜欢,内网根本不能用。因此一直在思考有没有办法用JS来代替。由于以前没有找到,所以也只有忍了,jcaptcha将就着用吧!但我发现Fancy时,我心动了,正好这几天有这个心情,决定花点时间把它应用到JAVA上来。首先到官方去看了一下,使用原理是:先从服务端获得一个0-4的数字(这个数字表示需要验证的是第几张图片),当把正确的图片拖到正确的位置时,生成一个隐藏的字段,这个字段的值就是这个随机数,当提交表单时,就把这个隐藏字段的值与服务端传过来的值比较,相等则通过。

由于官方的例子是采用PHP做的,本人从来没学过,也不打算学,所以不是很懂,看了个大概,基本算看懂了,但是采用JAVA来做,还是遇到了一些问题。

Fancy的文件主要有下面几个:
引用

-captcha
–imgs
–captcha.css
–jquery.captcha.js
–captcha.php
–iepngfix.htc
-latest-jquery
-latest-jquery-ui
-example.html
-readme.txt


由于官方的例子采用的PHP,所以里面含有PHP文件。实际上用JAVA时,有些文件是不需要的。

先从JSP说起,在JSP里需要做的事并不多,首先在头部引入声明:

...
<script type="text/javascript"
              src="${pageContext.request.contextPath}/js/jquery.js"></script>
<script type="text/javascript"
              src="${pageContext.request.contextPath}/js/jquery-ui-1.7.2.custom.min.js"></script>
<script type="text/javascript"
              src="${pageContext.request.contextPath}/captcha/jquery.captcha.js"></script>
              
<script type="text/javascript" charset="utf-8">
 $(function() {
 $(".ajax-fc-container").captcha({formId: "myForm"});
 });
 </script>
 
 <link rel="stylesheet" type="text/css" 
   href="${pageContext.request.contextPath}/captcha/captcha.css"></link>

...


需要注意的是要把form的ID做相应的修改,目录可以根据情况自己改变,当然jquery.captcha.js也要做相应的修改。经过上面声明以后,在相应的位置加入验证图片:

...
<div class="ajax-fc-container"></div>
...


JSP页面处理好以后,需要处理的就是JS代码了,JS代码其实很简单,就在jquery.captcha.js
文件内,这里需要注意两点:

一、验证的基本显示,例如把相应的英文改成相应的中文等,其实很简单,如:

...
var defaults = {  
	   borderColor: "",  
	   captchaDir: "captcha",  
	   url: "./RandomCaptcha.action?getNumber",  
	   formId: "myForm",  
	   text: "<font size='2'>验证你是一个人,<br />拖动 <span>scissors</span> 进入圆圈内.</font>",
	   items: Array("pencil", "scissors", "clock", "heart", "note") 
	  };
..


二、需要从服务端获得随机数字,这里需要用到AJAX请求,上面的URL就是相应的请求路径。getNumber表示请求执行此Action的getNumber方法,说到服务端,还真是麻烦,JAVA Web框架众多,但大多都复杂,就算古老的Struts,也依赖很多包,还要搞一堆配置,Struts2虽然功能强大,但用来照样有些复杂,更不用说其它的wicket,Tapestry了,就做一个简单的例子实在不想用那些复杂的框架,但是也不愿意直接用Servlet,还是Stripes好啊!功能强大,最让人称道的是它依赖的JAR特别少,只有一个common-logging文件,总算做了件好事。下面以Stripes为例,服务端的关键代码如下:

.....
	@DontValidate
	@HttpCache(allow = false)
	public Resolution getNumber() {

		return new StreamingResolution("text/plain") {
			@Override
			public void stream(HttpServletResponse response) throws Exception {
				int captcha = new Random().nextInt(5);
				response.getWriter().write(captcha + "");

			}
		};
	}
...


如果没用过Stripes的也不要紧,上面代码的意思就是返回一个数字字符串,不过别看着简单,其中出了一个问题,本人花了很长时间才解决,那就是那个看起来有点奇怪的captcha+"",理论上说,可以直接写成:

response.getWriter().write(captcha );


但实际上传过去的是乱码,这就奇怪了,如果是中文,出现乱码可能是字节编码的问题,怎么数字也会是乱码?这个问题搞了很久,还是不知道原因,以前也用过这种方式传数据,没出现什么问题呀,难道是框架的问题!仔细看了下框架的源码,也没发现什么问题呀!就这一个问题让自己引申出了一系列的问题(JQuery,Stripes,Servlet甚至tomcat),差点去研究JavaScriptResolution去了。最后发现字符格式的问题,虽然以前也用过,但是从来没有试过只传整数的方式。所以不得已,后面加个空字符串,总算解决了问题。

后来还是花了点时间,试用了一下JavaScriptResolution,可能稍微要简单一点,需要修改两个地方:
一、返回StreamingResolution修改成JavaScriptResolution:

...
public Resolution getNumber() {
		Random random = new Random();
		int captcha = new Random().nextInt(5);
		return new JavaScriptResolution(captcha);
	}
....


二、由于是以javascript的格式返回的,所以JavaScriptResolution在返回的数据后面加了个";",于是相应的JS文件也要修改,原来的代码:
...
var rand = $.ajax({ url: options.url,async: false }).responseText;
...


修改成:
...
var rand = eval($.ajax({ url: options.url,async: false }).responseText);
...


这样看起来似乎稍微要简单一点,当然JavaScriptResolution还有一些比较强大的功能,尤其是处理复杂的数据时,非常有用。

通过上面几步,就可以看见基本的效果了:

Ajax Fancy Capcha


在拖动图片到圆圈内时,Fancy会创建一个隐藏字段,代码如下:

...
$("#" + options.formId).append("<input type=\"hidden\" style=\"display: none;\" name=\"captcha\" value=\"" + rand + "\">");
...


这个字段的值就是从服务端传过来的数字,因此判断验证是否通过,只需要在服务端判断
字段captcha的值是否与刚才从服务端传过来的数字是否相等即可。

这样一个比较有创意的验证机制就做完啦!

你可能感兴趣的:(jquery,Ajax,PHP,框架,wicket)