Spring MVC 项目配置Kaptcha验证码
一般的网站注册和登录验证码都是用前端JS来实现的,只要前端验证成功就可以发送注册和登录的请求,这样如果受到来自网页和爬虫的攻击,验证码相当于形同虚设,后台服务器可能收到大量的http请求,严重影响服务器的性能。由此可见,如果由后台生成验证码之后展现给页面,页面每次的请求带上验证码信息到后台来比对会安全一些,成功再进行之后的操作,失败则返回提示信息。配置Kaptcha验证码正好可以完美达到此效果。本文介绍如何在Spring MVC项目中配置Kaptcha验证码。
Kaptcha介绍
kaptcha 是一个扩展自 simplecaptcha 的验证码库,在 Java 编程中 是一个非常实用的验证码生成工具。我们可以利用这个工具生成各种样式的验证码,因为它是可配置的,我们可以根据需求定制。
kaptcha 的工作原理是调用 com.google.code.kaptcha.servlet.KaptchaServlet ,生成一个验证码图片,响应到客户端,同时将生成的真是的验证码字符串放到 HttpSession 中。
使用kaptcha可以方便的配置
- 验证码的字体
- 验证码字体的大小
- 验证码字体的字体颜色
- 验证码内容的范围(数字,字母,中文汉字!)
- 验证码图片的大小,边框,边框粗细,边框颜色
- 验证码的干扰线(可以自己继承com.google.code.kaptcha.NoiseProducer写一个自定义的干扰线)
- 验证码的样式(鱼眼样式、3D、普通模糊……当然也可以继承com.google.code.kaptcha.GimpyEngine自定义样式)
Kaptcha使用方式
添加jar包依赖
1.如果不是maven项目,则需要到官网下载jar包,然后放入项目的lib文件夹中,再导入项目。下载地址:http://code.google.com/p/kaptcha/downloads/list
2. 如果是maven项目,在pom.xml中添加dependency
<!-- kaptcha -->
<dependency>
<groupId>com.google.code.kaptcha</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
本人测试maven库中几个kaptcha的jar包都下载不下来,所以在阿里的maven库找到kaptcha的dependency,亲测可以放心使用
<!-- kaptcha -->
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
在Spring配置文件中配置kaptcha的bean信息
<!-- google kaptcha的相关配置-->
<bean id="captchaProducer" class="com.google.code.kaptcha.impl.DefaultKaptcha">
<property name="config">
<bean class="com.google.code.kaptcha.util.Config">
<!--通过构造函数注入属性值 -->
<constructor-arg type="java.util.Properties">
<props>
<!-- 验证码宽度 -->
<prop key="kaptcha.image.width">100</prop>
<!-- 验证码高度 -->
<prop key="kaptcha.image.height">40</prop>
<!-- 生成验证码内容范围 -->
<prop key="kaptcha.textproducer.char.string">0123456789</prop>
<!-- 验证码个数 -->
<prop key="kaptcha.textproducer.char.length">4</prop>
<!-- 是否有边框 -->
<prop key="kaptcha.border">yes</prop>
<!-- 边框颜色 -->
<prop key="kaptcha.border.color">105,179,90</prop>
<!-- 边框厚度 -->
<prop key="kaptcha.border.thickness">1</prop>
<!-- 验证码字体颜色 -->
<prop key="kaptcha.textproducer.font.color">red</prop>
<!-- 验证码字体大小 -->
<prop key="kaptcha.textproducer.font.size">40</prop>
<!-- 验证码所属字体样式 -->
<prop key="kaptcha.textproducer.font.names">BKamrnBd</prop>
<!-- 干扰线颜色 -->
<prop key="kaptcha.noise.color">blue</prop>
<!-- 验证码文本字符间距 -->
<prop key="kaptcha.textproducer.char.space">3</prop>
</props>
</constructor-arg>
</bean>
</property>
</bean>
以上是参考配置,大家可根据自身需要进行修改,网上有好多kaptcha配置参数详解,这里就不赘述
Controller、Service、Model的实现
Controller
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.google.code.kaptcha.Producer;
import test.ImageCodeService;
@Controller
@RequestMapping("captcha")
public class CaptchaController {
Logger log = LoggerFactory.getLogger(getClass());
@Autowired Producer captchaProducer;
@Autowired ImageCodeService imageCodeService;
@RequestMapping(value = "/checkCaptchaCode", method = RequestMethod.GET)
public void getCaptchaCode(HttpServletRequest request, HttpServletResponse response) throws IOException{
HttpSession session = request.getSession();
response.setDateHeader("Expires", 0);
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
response.addHeader("Cache-Control", "post-check=0, pre-check=0");
response.setHeader("Pragma", "no-cache");
response.setContentType("image/jpeg");
//利用生成的字符串构建图片
BufferedImage bi = imageCodeService.generateImageCode(session.getId());
ServletOutputStream out = response.getOutputStream();
ImageIO.write(bi, "jpg", out);
try {
out.flush();
}catch(Exception e){
e.printStackTrace();
}
}
}
Service(生成验证码的方法执行后会将验证码以sessionId为标识存入数据库,并返回验证码图片,校验方法会根据传入的sessionId从数据库查找验证码信息,和传入的code进行比较,相同返回true)
import java.awt.image.BufferedImage;
public interface ImageCodeService {
/**
* 生成图片验证码并保存
* @param id
* @return
*/
public BufferedImage generateImageCode(String id);
/**
* 后台校验注册模块图片验证码
* @param id 唯一键,确定唯一性
* @param code 注册页面输入的验证码
* @return
*/
public boolean validImageCode (String id,String code);
}
import java.awt.image.BufferedImage;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.google.code.kaptcha.Producer;
import test.ImageCodeMapper;
import test.ImageCode;
import test.ImageCodeService;
@Service("imageCodeService")
public class ImageCodeServiceImpl implements ImageCodeService{
Logger log = LoggerFactory.getLogger(getClass());
@Autowired ImageCodeMapper imageCodeMapper;
@Autowired Producer captchaProducer;
/**
* 生成图片验证码并保存入数据库
* @param sessionId
* @return
*/
public BufferedImage generateImageCode(String sessionId){
//生成验证码文本
String capText = captchaProducer.createText();
Date now = new Date();
long expireLong = now.getTime() + 1000*60*5;
now.setTime(expireLong);
ImageCode imageCode = new ImageCode();
imageCode.setCode(capText);
imageCode.setExpire(0);
imageCode.setSessionKey(sessionId);
imageCode.setExpireTime(now);
imageCodeMapper.insert(imageCode);
//利用生成的字符串构建图片
BufferedImage bi = captchaProducer.createImage(capText);
return bi;
}
/**
* 校验图片验证码
* @param sessionId
* @return
*/
public boolean validImageCode (String sessionId,String code){
ImageCode imageCode = imageCodeMapper.selectByPrimaryKey(sessionId);
if(imageCode != null && imageCode.getExpire() == 0){
if(!imageCode.getCode().equals(code)){
return false;
}
return new Date().getTime() < imageCode.getExpireTime().getTime();
}
return false;
}
}
Model
import java.util.Date;
public class ImageCode {
private String sessionKey;
private Integer expire;
private Date expireTime;
private String code;
public String getSessionKey() {
return sessionKey;
}
public void setSessionKey(String sessionKey) {
this.sessionKey = sessionKey == null ? null : sessionKey.trim();
}
public Integer getExpire() {
return expire;
}
public void setExpire(Integer expire) {
this.expire = expire;
}
public Date getExpireTime() {
return expireTime;
}
public void setExpireTime(Date expireTime) {
this.expireTime = expireTime;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code == null ? null : code.trim();
}
}
页面代码
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>验证码</title>
</head>
<body>
<div class="proving-box clearfixed" id="imageCodeAuth">
<div class="proving-input">
<div class="input-box"><input type="text" id="authCode" value="图片验证码" /></div>
</div>
<img id="changeCaptcha" src="http://localhost:8080/captcha/checkCaptchaCode"/>
</body>
<script type="text/javascript">
$(function(){
$('img').click(function () {//点击验证码图片,重新生成验证码
$(this).attr('src', '/captcha/checkCaptchaCode?' + Math.floor(Math.random()*100) );
});
});
</script>
</html>
至此,kaptcha的配置就完成了,页面中即可显示验证码图片
kaptcha可配置项参考
kaptcha.border 是否有边框 默认为true 我们可以自己设置yes,no
kaptcha.border.color 边框颜色 默认为Color.BLACK
kaptcha.border.thickness 边框粗细度 默认为1
kaptcha.producer.impl 验证码生成器 默认为DefaultKaptcha
kaptcha.textproducer.impl 验证码文本生成器 默认为DefaultTextCreator
kaptcha.textproducer.char.string 验证码文本字符内容范围 默认为abcde2345678gfynmnpwx
kaptcha.textproducer.char.length 验证码文本字符长度 默认为5
kaptcha.textproducer.font.names 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
kaptcha.textproducer.font.size 验证码文本字符大小 默认为40
kaptcha.textproducer.font.color 验证码文本字符颜色 默认为Color.BLACK
kaptcha.textproducer.char.space 验证码文本字符间距 默认为2
kaptcha.noise.impl 验证码噪点生成对象 默认为DefaultNoise
kaptcha.noise.color 验证码噪点颜色 默认为Color.BLACK
kaptcha.obscurificator.impl 验证码样式引擎 默认为WaterRipple
kaptcha.word.impl 验证码文本字符渲染 默认为DefaultWordRenderer
kaptcha.background.impl 验证码背景生成器 默认为DefaultBackground
kaptcha.background.clear.from 验证码背景颜色渐进 默认为Color.LIGHT_GRAY
kaptcha.background.clear.to 验证码背景颜色渐进 默认为Color.WHITE
kaptcha.image.width 验证码图片宽度 默认为200
kaptcha.image.height 验证码图片高度 默认为50