这篇文章主要介绍了Java后台防止客户端重复请求,提交表单实现原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
<强>前言强>
在网络/应用程序项目中,有一些请求或操作会对数据产生影响(比如新增、删除,修改),针对这类请求一般都需要做一些保护,以防止用户有意或无意的重复发起这样的请求导致的数据错乱。
<强>常见处理方案
强>
1。客户端
例如表单提交后将提交按钮设为禁用等等方法…
2。服务端
前端的限制仅能解决少部分问题,且不够彻底,后端自有的防重复处理措施必不可少,义不容辞。
在此提供一个我在项目中用到的方案。简单来说就是判断请求url和数据是否和上一次相同。
<强>方法步骤强>
1。主要逻辑:
给所有的url加一个拦截器,每次请求将url存入会话,下次请求验证url数据是否相同,相同则拒绝访问。
当然,我在此基础上做了一些优化,比如:
使用会话有局限性,用户量大了以后服务器会撑不住,在此我使用了复述来替换。
加入了令牌令牌机制。
2。实现步骤:
2.1自定义一个注解
/* * * @Title: SameUrlData * @Description:自定义注解防止表单重复提交 * @Auther: xhq * @Version: 1.0 * @create 2019/3/26十43 */@Inherited @Target (ElementType.METHOD) @Retention (RetentionPolicy.RUNTIME) @Documented 公共@ interface SameUrlData { }
2.2自定义拦截器类
-
<李>检查此接口调用的方法是否使用了SameUrlData注解,若没有使用,表示此接口不需要校验;李>
<李>若使用了注解,获取请求url +参数,并去除一直在变化的参数(比如时间戳时间戳和签名标志)李>
<李>检查参数中是否有令牌参数(令牌代表不同的用户的唯一标识),没有直接放行李>
<李>有令牌参数,将牌+ url作为复述的关键,url +参数作为价值存入复述,并设定自动销毁时间李>
<李>再次访问进行验证是否重复请求李>
进口com.alibaba.fastjson.JSONObject; 进口com.tuohang.hydra.framework.common.spring.SpringKit; 进口com.tuohang.hydra.toolkit.basis.string.StringKit; 进口org.slf4j.Logger; 进口org.slf4j.LoggerFactory; 进口org.springframework.data.redis.core.StringRedisTemplate; 进口org.springframework.stereotype.Component; 进口org.springframework.web.method.HandlerMethod; 进口org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 进口javax.servlet.http.HttpServletRequest; 进口javax.servlet.http.HttpServletResponse; 进口java.lang.reflect.Method; 进口java.util.HashMap; 进口java.util.Iterator; 进口java.util.Map; 进口java.util.concurrent.TimeUnit;/* * * @Title:防止用户重复提交数据拦截器 * @Description:将用户访问的url和参数结合牌存入复述,每次访问进行验证是否重复请求接口 * @Auther: xhq * @Version: 1.0 * @create 2019/3/26大礼堂开幕 */@ component 公开课SameUrlDataInterceptor延伸HandlerInterceptorAdapter { 私有静态日志记录器=LoggerFactory.getLogger (SameUrlDataInterceptor.class);/* * *是否阻止提交,意见阻止,真正放行 * @return */@Override 公共布尔preHandle (HttpServletRequest请求,HttpServletResponse响应对象处理程序){抛出异常 如果处理程序instanceof HandlerMethod) { HandlerMethod HandlerMethod=(HandlerMethod)处理程序; 方法方法=handlerMethod.getMethod (); SameUrlData注释=method.getAnnotation (SameUrlData.class); 如果(注释!=null) { 如果(repeatDataValidator(请求)){//请求数据相同 日志。警告(“请不要重复提交url:“+ request.getServletPath ()); JSONObject结果=new JSONObject (); result.put (“statusCode”、“500”); result.put(“信息”、“请勿重复请求”); response.setCharacterEncoding (“utf - 8”); application/json response.setContentType (“;charset=utf - 8”); response.getWriter () .write (result.toString ()); .close response.getWriter () ();//拦截之后跳转页面//字符串formRequest=request.getRequestURI ();//请求。setAttribute (“myurl formRequest);//request.getRequestDispatcher (“/WebRoot/共同/错误/jsp/error_message.jsp”)。提出(请求、响应); 返回错误; 其他}{//如果不是重复相同数据 返回true; } } 返回true; 其他}{ 超级回报。preHandle(请求、响应处理程序); } }/* * *验证同一个url数据是否相同提交,相同返回现实 * @param httpServletRequest * @return */公共布尔repeatDataValidator (HttpServletRequest HttpServletRequest) {//获取请求参数地图 MapJava后台防止客户端重复请求,提交表单实现原理