为什么80%的码农都做不了架构师?>>>   

package com.yoro.core.web;import java.io.IOException;import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;/*** 防止表单重复提交 FORM TOKEN 过滤器 作用:1.防止用户后退操作,2.防止用户重复刷新操作* <li>*  利用TOKEN 防止重复提交需要结合特定场景,不要随意乱用*   1.有写业务是允许用户插入重复数据的,没必要使用*  2.有些业务是有状态控制的 重复提交有引发业务及验证 也没必要使用*  3.如类是于淘宝下单业务是不允许通过一个form 重复提交下单的 则可以利用token实现* <li>* 使用注意:* <li>* 1.如果结合springmvc 等其他mvc框架 使用 注意 addUrl 路径 不能 和  validUrl 路径 相同 * 只通过  get | post 提交方式区分调用的 action method  否则 点击后退安全不会读取浏览器缓存* </li>* @author zoro*/
public class XsrfTokenRequestFilter implements Filter {/*** addUrls ,validUrls , processUrls 三个数组长度必须相等一一对应*/private String[] addUrls; // 需要增加 TOKEN 的页面private String[] validUrls;// 需要验证TOEKN 的页面private String[] processUrls; // TOKEN 验证失败处理的页面FilterConfig filterConfig = null;public void init(FilterConfig filterConfig) throws ServletException {// 传入的参数分割符号String splitChar = filterConfig.getInitParameter("splitChar");if (StringUtils.isNotBlank(filterConfig.getInitParameter("addUrls"))) {addUrls = filterConfig.getInitParameter("addUrls").split(splitChar);}if (StringUtils.isNotBlank(filterConfig.getInitParameter("validUrls"))) {validUrls = filterConfig.getInitParameter("validUrls").split(splitChar);}if (StringUtils.isNotBlank(filterConfig.getInitParameter("processUrls"))) {processUrls = filterConfig.getInitParameter("processUrls").split(splitChar);}this.filterConfig = filterConfig;}public void destroy() {this.filterConfig = null;}@Overridepublic void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {// 获取请求路径String path = getRelativePath((HttpServletRequest) request);// 如果路径存在增加的urls列表里面,则向客户端增加一个token 参数if (ArrayUtils.contains(addUrls, path)) {xsrfTokenGenerator.save((HttpServletRequest) request,(HttpServletResponse) response);}// 如果路径存在验证urls列表里面 这获取客户端 token 参数做验证if (ArrayUtils.contains(validUrls, path)) {if (!xsrfTokenGenerator.validate((HttpServletRequest) request,(HttpServletResponse) response)) {// 验证没有通过则跳转到错误处理页面((HttpServletResponse) response).sendRedirect(processUrls[ArrayUtils.indexOf(validUrls,path)]);return;}}// 到了这里说明验证已经通过,则将客户端 token 删除 下次提交客户端cookie token 为空 重复提交则失败if (ArrayUtils.contains(validUrls, path)) {xsrfTokenGenerator.remove((HttpServletRequest) request,(HttpServletResponse) response);}chain.doFilter(request, response);}protected String getRelativePath(HttpServletRequest request) {if (request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null) {String result = (String) request.getAttribute(RequestDispatcher.INCLUDE_PATH_INFO);if (result == null) {result = (String) request.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH);} else {result = (String) request.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH)+ result;}if ((result == null) || (result.equals(""))) {result = "/";}return (result);}// No, extract the desired path directly from the requestString result = request.getPathInfo();if (result == null) {result = request.getServletPath();} else {result = request.getServletPath() + result;}if ((result == null) || (result.equals(""))) {result = "/";}return (result);}// 实例化 token 生成器private XsrfTokenGenerator xsrfTokenGenerator = new SimpleXsrfTokenGenerator();
}
package com.yoro.core.web;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public interface XsrfTokenGenerator {/*** 增加 TOKEN */public String save(HttpServletRequest request, HttpServletResponse response);/*** 删除TOKEN*/public void remove(HttpServletRequest request, HttpServletResponse response);/*** 验证TOKEN 是否有效 验证成功应当手动调用 remove 方法 手动从COOKIE中清除TOKEN*/public boolean validate(HttpServletRequest request, HttpServletResponse response);
}
package com.yoro.core.web;import java.util.UUID;import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.apache.commons.lang.StringUtils;import com.common.web.CookieUtils;/*** * 基于cookie 的 利用TOOKEN 防止表单重复提交的实现* * @author zoro* */
public class SimpleXsrfTokenGenerator implements XsrfTokenGenerator {/*** 默认TOOKEN 名称*/private final static String FORM_TOEKN_NAME = "_form_token";@Overridepublic boolean validate(HttpServletRequest request,HttpServletResponse response) {String paramString = request.getParameter(FORM_TOEKN_NAME);if (StringUtils.isBlank(paramString)) {return false;}String value = get(request);if (StringUtils.isBlank(value)) {return false;}return value.equals(paramString);}@Overridepublic String save(HttpServletRequest request, HttpServletResponse response) {String value = StringUtils.remove(UUID.randomUUID().toString(), "-");if (value != null) {set(request, response, value);}return value;}@Overridepublic void remove(HttpServletRequest request, HttpServletResponse response) {String value = get(request);if (value != null) {cancle(request, response);}}/*** 从cookie中获取TOKEN* * @param request* @return*/private String get(HttpServletRequest request) {Cookie cookie = CookieUtils.getCookie(request, FORM_TOEKN_NAME);return cookie == null ? null : cookie.getValue();}/*** 设置 TOKEN 到 COOKIE 当中* * @param request* @param response* @param value*/private void set(HttpServletRequest request, HttpServletResponse response,String value) {if (value != null) {CookieUtils.addCookie(request, response, FORM_TOEKN_NAME, value,-1, null);}if (value != null) {request.setAttribute(FORM_TOEKN_NAME, value);}}/*** 从COOKIE中清楚TOKEN* * @param request* @param response*/private void cancle(HttpServletRequest request, HttpServletResponse response) {CookieUtils.cancleCookie(request, response, FORM_TOEKN_NAME, null);}
}
package com.common.web;import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.springframework.util.Assert;/*** Cookie 辅助类* * @author hp* */
public class CookieUtils {/*** 每页条数cookie名称*/public static final String COOKIE_PAGE_SIZE = "_cookie_page_size";/*** 默认每页条数*/public static final int DEFAULT_SIZE = 20;/*** 最大每页条数*/public static final int MAX_SIZE = 200;/*** 获得cookie的每页条数* * 使用_cookie_page_size作为cookie name* * @param request*            HttpServletRequest* @return default:20 max:200*/public static int getPageSize(HttpServletRequest request) {Assert.notNull(request);Cookie cookie = getCookie(request, COOKIE_PAGE_SIZE);int count = 0;if (cookie != null) {if (NumberUtils.isDigits(cookie.getValue())) {count = Integer.parseInt(cookie.getValue());}}if (count <= 0) {count = DEFAULT_SIZE;} else if (count > MAX_SIZE) {count = MAX_SIZE;}return count;}/*** 获得cookie* * @param request*            HttpServletRequest* @param name*            cookie name* @return if exist return cookie, else return null.*/public static Cookie getCookie(HttpServletRequest request, String name) {Assert.notNull(request);Cookie[] cookies = request.getCookies();if (cookies != null && cookies.length > 0) {for (Cookie c : cookies) {if (c.getName().equals(name)) {return c;}}}return null;}/*** 根据部署路径,将cookie保存在根目录。* * @param request* @param response* @param name* @param value* @param expiry* @param domain* @return*/public static Cookie addCookie(HttpServletRequest request,HttpServletResponse response, String name, String value,Integer expiry, String domain) {Cookie cookie = new Cookie(name, value);if (expiry != null) {cookie.setMaxAge(expiry);}if (StringUtils.isNotBlank(domain)) {cookie.setDomain(domain);}String ctx = request.getContextPath();cookie.setPath(StringUtils.isBlank(ctx) ? "/" : ctx);response.addCookie(cookie);return cookie;}/*** 取消cookie* * @param request* @param response* @param name* @param domain*/public static void cancleCookie(HttpServletRequest request,HttpServletResponse response, String name, String domain) {Cookie cookie = new Cookie(name, "");cookie.setMaxAge(0);String ctx = request.getContextPath();cookie.setPath(StringUtils.isBlank(ctx) ? "/" : ctx);if (StringUtils.isNotBlank(domain)) {cookie.setDomain(domain);}response.addCookie(cookie);}
}
<!--@分隔 --><filter><filter-name>xsrfTokenRequestFilter</filter-name><filter-class>com.yoro.core.web.XsrfTokenRequestFilter</filter-class><init-param><param-name>splitChar</param-name><param-value>@</param-value></init-param><init-param><param-name>addUrls</param-name><param-value>/member/forgot_password.html;/login.html</param-value></init-param><init-param><param-name>validUrls</param-name><param-value>/member/forgot_password.jhtml;/login.jhtml</param-value></init-param><init-param><param-name>processUrls</param-name><param-value>/member/forgot_password.html;/login.html</param-value></init-param></filter><filter-mapping><filter-name>xsrfTokenRequestFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>

转载于:https://my.oschina.net/boltwu/blog/415749

利用token 防止表单重复提交相关推荐

  1. php token 表单重复提交,PHP生成token防止表单重复提交2个例子

    防止表单重复提交的解决方案非常的简单,我们下面两个例子都是生成一个随机的token验证用户是不是由我们站内提交并且进行重复验证即可实现了. 在网上搜索了一下有很多站长都这样说的 1.提交按钮置disa ...

  2. token防止表单重复提交

    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...

  3. python表单防重复提交_关于PHP使用token防止表单重复提交的方法

    这篇文章主要介绍了PHP使用token防止表单重复提交的方法,通过生成一个加密后的随机数存入session的token变量,同时将该值放入表单隐藏提交,达到防止表单重复提交的功能,需要的朋友可以参考下 ...

  4. struts2 自带的 token防止表单重复提交拦截器

    在struts2中,我们可以利用struts2自带的token拦截器轻松实现防止表单重复提交功能! 1. 在相应的action配置中增加:  <interceptor-ref name=&quo ...

  5. SpringMVC中实现的token,防表单重复提交

    一:首先创建一个token处理类  ,这里的类名叫 TokenHandler private static Logger logger = Logger.getLogger(TokenHandler. ...

  6. 利用session防止表单重复提交

    1.是什么?一个表单不能多次提交: 2.为什么? 在网络不好或者并发请求时会导致多次重复提交数据的问题.防止重复提交,可以维护数据一致性: 3.怎么做? 把 session的编号和当前时间戳经过 MD ...

  7. 5位随机数重复的概率 php_php防止表单重复提交的方法

    Token,就是令牌,最大的特点就是随机性,不可预测. Token一般用在两个地方--防止表单重复提交.anti csrf攻击(跨站点请求伪造). 两者在原理上都是通过session token来实现 ...

  8. JavaWeb学习总结(十三)——使用Session防止表单重复提交

    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...

  9. JAVA_OA(十四)番外:JAVAWEB防止表单重复提交的方法整合(包括集群部署)

    因为自己要用,所以查找了网络上javaweb项目防止表单重复提交的方法,有些部分不太好找,所以整合后贴出来,首先是孤傲苍狼的一部分博客文章,集群部署的解决方案在后面(注意大红字) 原文出处:孤傲苍狼的 ...

  10. java怎么防止表单重复提交_如何防止表单重复提交

    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...

最新文章

  1. Microsoft NLayerApp案例理论与实践 - 项目简“.NET研究”介与环境搭建
  2. 判断文件是否损坏_判断Excel文件是否已打开
  3. jQuery的JSONP
  4. VTK:Medical之MedicalDemo2
  5. Rails Minitest style 指南
  6. 分布式文件系统之MogileFS的使用
  7. python3 namedtuple_去年发布的Python 3.8 稳定版,帮你们来一波特性全面解读
  8. 我跟 17 位顶级游戏策划人学到的 3 个产品方法论
  9. 对自己编译的文件(exe/dll)进行签名的实践(Windows)
  10. Web笔记:jQuery的使用
  11. uclient uc oracle,UClient下载
  12. PHP怎么获得斗鱼TV源地址,如何获取视频的直播源地址
  13. 11(0)-AirSim+四旋翼仿真-人工势场法避障
  14. JSP基础教程之表单编辑
  15. html新浪短域名api,新浪短网址API接口
  16. 计算机图像处理实验二 图像直方图及灰度变换
  17. 360无线网卡linux驱动下载,如何在Linux下写无线网卡的驱动
  18. 【Sciter】Sciter 结合 Preact 封装 图片查看器总结
  19. 存钱罐小程序_一罐来统治所有人
  20. 干货!万字设计模式面试题,再也不需要怂面试官了!

热门文章

  1. paip. http 405 的解决..
  2. paip.提升开发效率--使用拼音
  3. 汉字乱码的终极解决方案
  4. Julia: PkgMirrors,提升库下载速度
  5. Rust : codewars的up AND down 算法
  6. Julia: 关于下载库时WinRPM的Bug
  7. 七年!未来数据库的拐点已至
  8. 倒计时1周!聚焦金融科技,Gdevops北京站即将启程
  9. 【数字信号调制】基于matlab GUI AM+FM+DSB+SSB调制解调【含Matlab源码 1212期】
  10. 【价格预测】基于matlab粒子群算法黄金价格预测【含Matlab源码 591期】