欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Ajax Fancy Capcha

程序员文章站 2022-07-15 11:20:45
...
几天前看见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
            
    
    博客分类: View显示 AjaxjQueryPHP框架wicket 


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

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


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

这样一个比较有创意的验证机制就做完啦!
  • Ajax Fancy Capcha
            
    
    博客分类: View显示 AjaxjQueryPHP框架wicket 
  • 大小: 7.7 KB