经过在github和google code上搜索之后,初步选择了两种方案:jQuery.buttonCaptcha 和 kaptcha。
jQuery.buttonCaptcha需要引用jquery一系列文件,对于没有采用jquery的系统中会造成加载资源过多,影响页面速度。
Kaptcha使用java来生成验证码,可配置(自定义)验证码的类型(中文,字母,数字)、字体类型、字体颜色、图片的宽度和高度、图片边框、干扰线、样式等。可配置,因此使用方便;而且支持扩展。
基于以上判断,我建议使用kaptcha。
Kaptcha使用很方便,通过servlet来访问。在web项目中,可以这样配置。
在页面中,可以这样使用
Kaptcha在生成验证码图片的同时,会将验证码的内容放入session中,key是com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY。这样,我们就可以在服务端验证用户输入的验证码是否正确了。
以上配置是针对普通web项目的,如果采用了spring mvc框架的项目,要采取另外一种配置方式,这种配置方式session中无法获得验证码的值。
在spring mvc中,要为它单独配置一个controller
首先新建一个文件 applicationContext-kaptcha.xml
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
之后,新建一个controller
package cn.com.gei.htic.platform.portal.controller;
importjava.awt.image.BufferedImage;
import javax.imageio.ImageIO;
importjavax.servlet.ServletOutputStream;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Controller;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.servlet.ModelAndView;
importcom.google.code.kaptcha.Constants;
importcom.google.code.kaptcha.Producer;
@Controller
@RequestMapping("/kaptcha")
@Controller
public classKaptchaController {
privateProducer captchaProducer = null;
@Autowired
publicvoid setCaptchaProducer(Producer captchaProducer) {
this.captchaProducer= captchaProducer;
}
@RequestMapping("/captcha-image")
publicModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
response.setDateHeader("Expires", 0);
// Set standard HTTP/1.1 no-cache headers.
response.setHeader("Cache-Control",
"no-store, no-cache, must-revalidate");
// Set IE extended HTTP/1.1 no-cache headers (use addHeader).
response.addHeader("Cache-Control","post-check=0, pre-check=0");
// Set standard HTTP/1.0 no-cache header.
response.setHeader("Pragma", "no-cache");
// return a jpeg
response.setContentType("image/jpeg");
// create the text for the image
String capText = captchaProducer.createText();
// store the text in the session
request.getSession().setAttribute(Constants.KAPTCHA_SESSION_KEY,
capText);
// create the image with the text
BufferedImage bi = captchaProducer.createImage(capText);
ServletOutputStream out = response.getOutputStream();
// write the data out
ImageIO.write(bi, "jpg", out);
try {
out.flush();
} finally {
out.close();
}
return null;
}
}
然后新建一个aptcha-servlet.xml,放在WEB-INF下
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
base-package=" cn.com.gei.htic.platform.portal.controller"/>
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
value="org.springframework.web.servlet.view.JstlView"/>
最后在web.xml中配置
在页面中,可以通过如下方式来使用:
参考:http://ttaale.iteye.com/blog/808719
这里 的与Spring Security结合,是指登录页面的验证码验证问题。
首先在Spring Security的配置文件中增加如下内容:
意思是不对验证码进行权限验证
之后要自定义一个filter
在
PRE_AUTH_FILTER的意思是在Spring Security验证之前进行的验证,具体可以参考这里
http://static.springsource.org/spring-security/site/docs/3.0.x/reference/preauth.html
之后增加aptchaFilter的定义
class="cn.com.gei.kmp4.kjjexternal.security.filter.AptchaFilter">
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
引用的authenticationManager是别名
其中loginSuccessHandler可以采用kmp4默认的。
AptchaFilter的定义如下:
public class AptchaFilterextends UsernamePasswordAuthenticationFilter {
@Override
public Authentication attemptAuthentication(HttpServletRequestrequest,
HttpServletResponse response) throws AuthenticationException{
checkValidateCode(request);
return super.attemptAuthentication(request, response);
}
protected void checkValidateCode(HttpServletRequest request) {
String sessionValidateCode =obtainSessionValidateCode(request);
String validateCodeParameter =obtainValidateCodeParameter(request);
if (sessionValidateCode != null
&&!sessionValidateCode.equalsIgnoreCase(validateCodeParameter)) {
throw new AuthenticationServiceException(messages
.getMessage("validateCode.notEquals"));
}
}
private String obtainSessionValidateCode(HttpServletRequestrequest) {
HttpSession session = request.getSession(true);
String code = (String) session
.getAttribute(Constants.KAPTCHA_SESSION_KEY);
return code;
}
private String obtainValidateCodeParameter(HttpServletRequestrequest) {
//yanzheng 是页面中验证码输入框的name
return request.getParameter("yanzheng");
}
}
此filter继承自 UsernamePasswordAuthenticationFilter,重写了attemptAuthentication方法,在此方法中,我们可以增加对验证码的验证逻辑
如果验证失败,则抛出AuthenticationServiceException异常,异常的提示信息可以结合本地message策略,在org/springframework/security/messages_zh_CN.properties中增加一条,这里采用的是
validateCode.notEquals 验证码不正确
通过配置simpleUrlAuthenticationFailureHandler,我们就可以在这个filter验证失败后,将页面重定向到登录页面,从而实现验证码的验证了。
Constant |
Description |
Default |
常数 |
描述 |
默认值 |
kaptcha.border |
有无边框,选项是yes或者no |
Yes |
kaptcha.border.color |
边框颜色。可选值为red,green,blue 或者white,black,blue |
Black |
kaptcha.border.thickness |
边框厚度,可选值为大于0的整数 |
1 |
kaptcha.image.width |
图片宽度(像素) |
200 |
kaptcha.image.height |
图片高度(像素) |
50 |
kaptcha.producer.impl |
图片生产者 |
com.google.code.kaptcha.impl.DefaultKaptcha (可自定义,实现Producer接口即可) |
kaptcha.textproducer.impl |
字体产生者 |
com.google.code.kaptcha.text.impl.DefaultTextCreator(可自定义,实现TextProducer接口即可) |
kaptcha.textproducer.char.string |
图片内容从这些字符中产生 |
abcde2345678gfynmnpwx |
kaptcha.textproducer.char.length |
图片内容的长度 |
5 |
kaptcha.textproducer.font.names |
图片字体名,用逗号隔开。 |
Arial, Courier |
kaptcha.textproducer.font.size |
图片字体大小 |
40px |
kaptcha.textproducer.font.color |
图片字体颜色,可选值为red,green,black等 |
black |
kaptcha.textproducer.char.space |
字符之间空格数 |
2 |
kaptcha.noise.impl |
噪度生产者 |
com.google.code.kaptcha.impl.DefaultNoise (可自定义,实现NoiseProducer接口即可) |
kaptcha.noise.color |
噪度颜色,可选值为red,green,black等 |
Black |
kaptcha.obscurificator.impl |
模糊度实现者 |
com.google.code.kaptcha.impl.WaterRipple (可自定义,实现GimpyEngine接口即可) |
kaptcha.background.impl |
背景实现者 |
com.google.code.kaptcha.impl.DefaultBackground(可自定义,实现BackgroundProducer接口即可) |
kaptcha.background.clear.from |
背景颜色开始值,可选值是red,green,blue等 |
Light grey |
kaptcha.background.clear.to |
背景颜色结束值,可选值是red,green,blue |
White |
kaptcha.word.impl |
字体渲染实现者 |
com.google.code.kaptcha.text.impl.DefaultWordRenderer(可自定义,实现WordRenderer接口即可) |
kaptcha.session.key |
验证码内容生成后会放入HttpSession中,这是内容在session中的key值 |
KAPTCHA_SESSION_KEY (程序有bug,建议不要配,程序中可通过session.getAttribute(Constants.KAPTCHA_SESSION_KEY)来取) |
kaptcha.session.date |
验证码生成的日期会放入HttpSession中,这是日期在session中的key值 |
KAPTCHA_SESSION_DATE |
// 点击刷新验证码
$(function(){
$('#id_captchaImage').click(function(){
$(this).hide().attr('src','/kaptcha/captcha-image?'+ Math.floor(Math.random()*100)).fadeIn();
});
});