谷歌验证码非web.xml非servlet拦截 使用配置文件自定义加载,防止多次点击(防js攻击)

因业务需要不能使用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;
	
}








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值