再做系统的时候,其实经常会遇上重复请求这个问题,虽然一般前端都会做一些防重复点击的操作,但是,这个玩意儿是没办法防止某些恶性操作的,并且,前端也不一定说就完全屏蔽了用户的重复点击操作。微微研究了一下,搞了一个简易版的防刷系统,不过占用的内存,并发这些玩意儿我还没测试过哦,下面直接贴代码
1.请求拦截器
public class AntiBrushInterceptor implements HandlerInterceptor { /** * 请求前 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //启用简单版防刷 check = CodeConfig.transfer(AntiBrushCache.simpleCheck(request),request,response); return check; } /** * 处理后 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView){ //获取url String url = request.getMethod()+request.getServletPath(); //获取该次请求的ip String ip = Tool.getRealIp(request); try{ AntiBrushCache.url_number.get(url).get(ip).set(0); }catch (Exception e){ logger.error(e); if (AntiBrushCache.url_number.get(url) == null){ AtomicInteger number = new AtomicInteger(); ConcurrentHashMap<String,AtomicInteger> concurrentHashMap = new ConcurrentHashMap<>(); concurrentHashMap.put(ip,number); AntiBrushCache.url_number.put(url,concurrentHashMap); } } System.out.println(request.hashCode()+":"+response.getStatus()+":"+System.currentTimeMillis()); } /** * 返回后 */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { }
2.访问控制的具体实现代码
public class AntiBrushCache { public static volatile ConcurrentHashMap<String,Integer> url_time = new ConcurrentHashMap<>(); public static final Boolean check = true; /** * key --> url * value --> {Key--> ip地址 ,value --> 访问累计器} */ public static volatile ConcurrentHashMap<String,ConcurrentHashMap<String,AtomicInteger>> url_number = new ConcurrentHashMap<>(); /** * 监测url是否通过监测 * @return 200 通过监测,100 不通过 */ public static Integer simpleCheck(HttpServletRequest request){ //获取url String url = request.getMethod()+request.getServletPath(); //获取该请求真实ip String ip = Tool.getRealIp(request);
//获取该ip上次请求时间 String ip = Tool.getRealIp(request); //原子计数器统计访问数值 AtomicInteger number; ConcurrentHashMap<String,AtomicInteger> concurrentHashMap = url_number.get(url); if (concurrentHashMap == null){ synchronized (check){ if (url_number.get(url) == null){ number = new AtomicInteger(); concurrentHashMap = new ConcurrentHashMap<>(); concurrentHashMap.put(ip,number); url_number.put(url,concurrentHashMap); }else{ return 100; } } }else{ number = concurrentHashMap.get(ip); } number.addAndGet(1); //number过大时,则同步访问过快,直接拦截 if (number.get() >= 2){ AntiBrushCache.url_number.get(url).get(ip).addAndGet(-1); return 100; } return 200;
}
}3:这个拦截系统只要有访问··就会产生记录放在内存,所以··还是要定时清洗下会比较好的
4:启动这个拦截器只需要在spring的配置文件上加上一个拦截器就好了
<!--防刷拦截器--> <mvc:interceptor> <mvc:mapping path="/**" /> <mvc:exclude-mapping path="/" /> <mvc:exclude-mapping path="/**/*.html"/> <mvc:exclude-mapping path="/**/*.css"/> <mvc:exclude-mapping path="/**/*.js"/> <mvc:exclude-mapping path="/**/*.png"/> <mvc:exclude-mapping path="/**/*.gif"/> <mvc:exclude-mapping path="/**/*.jpg"/> <mvc:exclude-mapping path="/**/*.jpeg"/> <bean class="com.simba.safety.antiBrush.Interceptor.AntiBrushInterceptor"/> </mvc:interceptor>