1 importcom.alibaba.fastjson.JSONObject;2 importcom.tuohang.hydra.framework.common.spring.SpringKit;3 importcom.tuohang.hydra.toolkit.basis.string.StringKit;4 importorg.slf4j.Logger;5 importorg.slf4j.LoggerFactory;6 importorg.springframework.data.redis.core.StringRedisTemplate;7 importorg.springframework.stereotype.Component;8 importorg.springframework.web.method.HandlerMethod;9 importorg.springframework.web.servlet.handler.HandlerInterceptorAdapter;10
11 importjavax.servlet.http.HttpServletRequest;12 importjavax.servlet.http.HttpServletResponse;13 importjava.lang.reflect.Method;14 importjava.util.HashMap;15 importjava.util.Iterator;16 importjava.util.Map;17 importjava.util.concurrent.TimeUnit;18
19 /**
20 * @Title: 防止用户重复提交数据拦截器21 * @Description: 将用户访问的url和参数结合token存入redis,每次访问进行验证是否重复请求接口22 * @Auther: xhq23 * @Version: 1.024 * @create 2019/3/26 10:3525 */
26 @Component27 public class SameUrlDataInterceptor extendsHandlerInterceptorAdapter {28
29 private static Logger LOG = LoggerFactory.getLogger(SameUrlDataInterceptor.class);30
31 /**
32 * 是否阻止提交,fasle阻止,true放行33 *@return
34 */
35 @Override36 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throwsException {37 if (handler instanceofHandlerMethod) {38 HandlerMethod handlerMethod =(HandlerMethod) handler;39 Method method =handlerMethod.getMethod();40 SameUrlData annotation = method.getAnnotation(SameUrlData.class);41 if (annotation != null) {42 if(repeatDataValidator(request)){43 //请求数据相同
44 LOG.warn("please don't repeat submit,url:"+request.getServletPath());45 JSONObject result = newJSONObject();46 result.put("statusCode","500");47 result.put("message","请勿重复请求");48 response.setCharacterEncoding("UTF-8");49 response.setContentType("application/json; charset=utf-8");50 response.getWriter().write(result.toString());51 response.getWriter().close();52 //拦截之后跳转页面53 //String formRequest = request.getRequestURI();54 //request.setAttribute("myurl", formRequest);55 //request.getRequestDispatcher("/WebRoot/common/error/jsp/error_message.jsp").forward(request, response);
56 return false;57 }else {//如果不是重复相同数据
58 return true;59 }60 }61 return true;62 } else{63 return super.preHandle(request, response, handler);64 }65 }66 /**
67 * 验证同一个url数据是否相同提交,相同返回true68 *@paramhttpServletRequest69 *@return
70 */
71 public booleanrepeatDataValidator(HttpServletRequest httpServletRequest){72 //获取请求参数map
73 Map parameterMap =httpServletRequest.getParameterMap();74 Iterator> it =parameterMap.entrySet().iterator();75 String token = "";76 Map parameterMapNew = new HashMap<>();77 while(it.hasNext()){78 Map.Entry entry =it.next();79 if(!entry.getKey().equals("timeStamp") && !entry.getKey().equals("sign")){80 //去除sign和timeStamp这两个参数,因为这两个参数一直在变化
81 parameterMapNew.put(entry.getKey(), entry.getValue());82 if(entry.getKey().equals("token")) {83 token = entry.getValue()[0];84 }85 }86 }87 if(StringKit.isBlank(token)){88 //如果没有token,直接放行
89 return false;90 }91 //过滤过后的请求内容
92 String params =JSONObject.toJSONString(parameterMapNew);93
94 System.out.println("params==========="+params);95
96 String url =httpServletRequest.getRequestURI();97 Map map = new HashMap<>();98 //key为接口,value为参数
99 map.put(url, params);100 String nowUrlParams =map.toString();101
102 StringRedisTemplate smsRedisTemplate = SpringKit.getBean(StringRedisTemplate.class);103 String redisKey = token +url;104 String preUrlParams =smsRedisTemplate.opsForValue().get(redisKey);105 if(preUrlParams == null){106 //如果上一个数据为null,表示还没有访问页面107 //存放并且设置有效期,2秒
108 smsRedisTemplate.opsForValue().set(redisKey, nowUrlParams, 2, TimeUnit.SECONDS);109 return false;110 }else{//否则,已经访问过页面
111 if(preUrlParams.equals(nowUrlParams)){112 //如果上次url+数据和本次url+数据相同,则表示重复添加数据
113 return true;114 }else{//如果上次 url+数据 和本次url加数据不同,则不是重复提交
115 smsRedisTemplate.opsForValue().set(redisKey, nowUrlParams, 1, TimeUnit.SECONDS);116 return false;117 }118 }119 }120 }