因业务需要不能使用servlet方式生成验证码
package com.pbh.controller.sys;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
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.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.google.code.kaptcha.Producer;
import com.google.code.kaptcha.util.Config;
import com.lianshangche.config.GlobalConfig;
import com.pbh.util.IPUtil;
import com.pbh.util.VisitorUtil;
/**
*
* Title:CaptchaController
* Description:使用google captcha生成验证码
* @date 2017年8月15日 下午5:19:17
*/
@Controller(value = "admin.CaptchaController")
@RequestMapping("/captcha")
public class CaptchaController {
private Properties props = new Properties();
private Producer kaptchaProducer = null;
/**
* 生成验证码
* @param request
* @param response
* @return
* @throws IOException
*/
@RequestMapping("/getCaptchaCode")
public ModelAndView 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");
//防止频繁点击
if (!VisitorUtil.isFrequentAccess(request, "captchaImgs")) {
String jsessionId = session.getId();
//加载配置
String path = CaptchaController.class.getClassLoader().getResource("kaptcha.properties").getPath().replace("file:/", "");//获取运行时绝对路径
FileInputStream fis = new FileInputStream(path);
this.props.load(fis);
Config config = new Config(this.props);
this.kaptchaProducer = config.getProducerImpl();
//生成验证码文本
String capText = this.kaptchaProducer.createText();
GlobalConfig.captchaMap.put(jsessionId, capText.toLowerCase());//保存验证码到全局map里
//利用生成的字符串构建图片
BufferedImage bImage = this.kaptchaProducer.createImage(capText);
ServletOutputStream out = response.getOutputStream();
ImageIO.write(bImage, "jpg", out);
try {
out.flush();
} finally {
out.close();
}
}else{
System.out.println(IPUtil.getIpAddr(request)+"访问验证码过于频繁");
}
return null;
}
}
kaptcha.properties文件放在resources下
kaptcha.border=no
kaptcha.textproducer.font.size=45
kaptcha.textproducer.char.string=abcdefnmnwx235678ABCDEFGHKQRSTX
kaptcha.background.clear.from=196,229,248
kaptcha.background.clear.to=196,229,248
kaptcha.textproducer.char.length=4
kaptcha.obscurificator.impl=com.google.code.kaptcha.impl.WaterRipple
工具类
获取用户真实IP
/**
2017年1月22日
IPUtils.java
*/
package com.pbh.util;
import javax.servlet.http.HttpServletRequest;
/**
* @date 2017年1月22日 下午1:10:16
* @version V1.0
*/
public class IPUtil {
/**
* 根据请求,返回求IP地址
*
* @param request
* @return String
*/
public static String getIpAddr(HttpServletRequest request) {
String ip = request.getHeader(" x-forwarded-for ");
if (ip == null || ip.length() == 0 || " unknown ".equalsIgnoreCase(ip)) {
ip = request.getHeader(" Proxy-Client-IP ");
}
if (ip == null || ip.length() == 0 || " unknown ".equalsIgnoreCase(ip)) {
ip = request.getHeader(" WL-Proxy-Client-IP ");
}
if (ip == null || ip.length() == 0 || " unknown ".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}
防止频繁点击按钮
package com.pbh.util;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
/**
*
* Title:VisitorUtil
* Description:防止频繁点击按钮
* @date 2017年8月15日 下午3:32:45
*/
public class VisitorUtil {
public static boolean isFrequentAccess(HttpServletRequest request,String sessionName) {
//防止频繁点击(3秒5次)
String sessionID = request.getSession().getId();//会话ID
@SuppressWarnings("unchecked")
Map
visitors = (Map
) request.getSession().getAttribute(sessionName);
Date now =new Date();
if (visitors!=null) {
Visitor vis = visitors.get(sessionID);//通过sessionID查找访问者
if(vis!= null){//找到访问者,则说明该用户为再次访问
//小于10秒,但访问超过10次
vis.getRequestTimeQueue().insert(now.getTime());//插入当前请求时间
//得到最后一次和第一次的访问时间差
Long span = vis.getRequestTimeQueue().getLast() - vis.getRequestTimeQueue().getFirst();
if(span < 3000 && vis.getRequestTimeQueue().getLast() != 0) {//频繁访问
return true;
}
} else {
//当前访问者为初次访问
ArrayTime timeQueue = new ArrayTime();
timeQueue.setLength(5);
timeQueue.init();
vis=new Visitor();
vis.setSessionID(sessionID);
vis.setRequestTimeQueue(timeQueue);
vis.getRequestTimeQueue().insert(now.getTime());
visitors.put(sessionID,vis);
request.getSession().setAttribute(sessionName, visitors);
return false;
}
}else{//ADMIN端还没有点击过登录
//当前访问者为初次访问
ArrayTime timeQueue = new ArrayTime();
timeQueue.setLength(5);//
timeQueue.init();
Visitor vis=new Visitor();
vis.setSessionID(sessionID);
vis.setRequestTimeQueue(timeQueue);
vis.getRequestTimeQueue().insert(now.getTime());
visitors = new HashMap
();
visitors.put(sessionID,vis);
request.getSession().setAttribute(sessionName, visitors);
return false;
}
return false;
}
}
相关代码
package com.pbh.util;
/**
*
* Title:Visitor
* Description:客户端的访问者
* @author PanBaihui
* @date 2017年8月15日 上午11:43:00
*/
public class Visitor {
/*
* Creates a new instance of Visitor 外网访问者,以sessionID作为标识
* 违反访问规则将不予处理请求
*/
private String sessionID = null;
private ArrayTime requestTimeQueue = new ArrayTime();
public Visitor() {
}
public void setSessionID(String sessionID) {
this.sessionID = sessionID;
}
public String getSessionID() {
return this.sessionID;
}
public void setRequestTimeQueue(ArrayTime requestTimeQueue) {
this.requestTimeQueue = requestTimeQueue;
}
public ArrayTime getRequestTimeQueue() {
return this.requestTimeQueue;
}
}
package com.pbh.util;
/**
*
* Title:ArrayTime
* Description:用户的访问时间序列
* @author PanBaihui
* @date 2017年8月15日 上午11:40:49
*/
public class ArrayTime {
private long[] time;
private int length = 10; // 默认为十次(10s内刷新10次则违反规则)
public ArrayTime() {
}
public void init() {
time = new long[length];
}
public int getLength() {
return this.length;
}
public void setLength(int len) {
this.length = len;
}
public long getLast() {
return this.time[length - 1];
}
public long getFirst() {
return this.time[0];
}
public long getElement(int i) {
return time[i];
}
public void insert(long nextTime) {
if (this.getLast() != 0)// 数组已经满了
{
// 去掉首元素,将数组元素顺序前移,nextTime插到最后
for (int i = 0; i < this.length - 1; i++) {
time[i] = time[i + 1];
}
this.time[length - 1] = nextTime;
} else {
// 插到下一个,不用排序
int j = 0;
while (time[j] != 0) {
j++;
}
time[j] = nextTime;
}
}
}
package com.pbh.config;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
public class GlobalConfig {
/**
* 访问间隔时间,目前设置为3秒
*/
public static long interval = 3000;
/**
* 访问间隔时间内最大点击次数,目前设置为10秒内10次
*/
public static int maxCount = 5;
}