利用session防止表单重复提交

1、是什么?一个表单不能多次提交;

2、为什么? 在网络不好或者并发请求时会导致多次重复提交数据的问题。防止重复提交,可以维护数据一致性;

3、怎么做? 把 session的编号和当前时间戳经过 MD5 加密得到token并存入 session;更多token 介绍参见 https://blog.csdn.net/PacosonSWJTU/article/details/109958455  

更多加密算法介绍(MD5, SHA, AES, DES ),参见  https://blog.csdn.net/PacosonSWJTU/article/details/109954811

 

【荔枝】转自 张孝祥  

token 生成方式如下:  (更加通用的方法是,把 用户名,密码当做加密源进行加密,得到摘要作为token) 

/*** 产生表单标识号并将之保存在当前用户Session中。**@param request 封装当前请求消息的HttpServletRequest对象*/public synchronized void saveToken(HttpServletRequest request){HttpSession session = request.getSession();try {byte id[] = session.getId().getBytes();long current = System.currentTimeMillis();if (current == previous){current++;}previous = current;byte now[] = String.valueOf(current).getBytes();// 基于MD5加密 MessageDigest md = MessageDigest.getInstance("MD5");md.update(id);md.update(now);String token = toHex(md.digest());session.setAttribute(FORM_TOKEN_KEY, token);}catch (NoSuchAlgorithmException e){;}}

生成表单的servlet,该表单会带上token; (有token,可以理解为已经登录了,登录信息加密为token令牌) 

// 填写表单
public class FormGenerateServlet extends HttpServlet
{public void service(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException{response.setContentType("text/html;charset=GB2312");PrintWriter out = response.getWriter();TokenProcessor.getInstance().saveToken(request);String token = (String)request.getSession().getAttribute(TokenProcessor.FORM_TOKEN_KEY);out.println("<form action='FormDealServlet'" + "method='POST'>" +"<input type='hidden' name='" + TokenProcessor.FORM_TOKEN_KEY + "' value='" + token + "'>" +"字段1:<input type='text' name='p1'><br>" +"<input type='submit' value='提交'> " +"</form>");}
}

处理逻辑servlet DealServlet, 可以看到, 一旦提交成功, 该servlet 会把 token 从 会话移除, 防止二次提交; 

// 表单处理逻辑 servlet 
public class FormDealServlet extends HttpServlet
{public void service(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException{response.setContentType("text/html;charset=GB2312");PrintWriter out = response.getWriter();	TokenProcessor tokenProcessor = TokenProcessor.getInstance();if(!tokenProcessor.isTokenValid(request)){out.println("这是重复或非法提交!");return;}String p1 = request.getParameter("p1");if(p1==null || p1.trim().equals("")){out.println("请输入内容!");}else{out.println("提交内容已被处理!");tokenProcessor.resetToken(request); // 一旦处理成功, 移除掉token ,防止2次重复提交 }}
}

=========== TokenProcessor全部代码如下:


// token标识处理器 
public class TokenProcessor
{private long previous;  //上次生成表单标识号的时间值private static TokenProcessor instance = new TokenProcessor();public static String FORM_TOKEN_KEY = "FORM_TOKEN_KEY";private TokenProcessor(){}public static TokenProcessor getInstance(){return instance;}/***验证请求消息中的标识号是否有效,如果请求消息中的表单标识号与当前*用户的Session域中的表单标识号相同,返回结果为true,否则返回false。**@param request 封装当前请求消息的HttpServletRequest对象*/public synchronized boolean isTokenValid(HttpServletRequest request){/*为避免Session对象不存在时创建Session对象,下面的语句不用request.getSession()*/HttpSession session = request.getSession(false);if (session == null){return false;}String saved = (String) session.getAttribute(FORM_TOKEN_KEY);if (saved == null){return false;}String token = request.getParameter(FORM_TOKEN_KEY);if (token == null){return false;}return saved.equals(token);}/*** 清除存储在当前用户Session中的表单标识号。**@param request 封装当前请求消息的HttpServletRequest对象*/public synchronized void resetToken(HttpServletRequest request){HttpSession session = request.getSession(false);if (session == null){return;}session.removeAttribute(FORM_TOKEN_KEY);}/*** 产生表单标识号并将之保存在当前用户Session中。**@param request 封装当前请求消息的HttpServletRequest对象*/public synchronized void saveToken(HttpServletRequest request){HttpSession session = request.getSession();try {byte id[] = session.getId().getBytes();long current = System.currentTimeMillis();if (current == previous){current++;}previous = current;byte now[] = String.valueOf(current).getBytes();// 基于MD5加密 MessageDigest md = MessageDigest.getInstance("MD5");md.update(id);md.update(now);String token = toHex(md.digest());session.setAttribute(FORM_TOKEN_KEY, token);}catch (NoSuchAlgorithmException e){;}}/*** 将一个字节数组转换成十六进制的字符串形式返回。* @param buffer 要被转换的字节数组*/private String toHex(byte buffer[]){StringBuffer sb = new StringBuffer(buffer.length * 2);for (int i = 0; i < buffer.length; i++){sb.append(Character.forDigit((buffer[i] & 0xf0) >> 4, 16));sb.append(Character.forDigit(buffer[i] & 0x0f, 16));}return sb.toString();}
}


4、访问记录 

步骤1, 

步骤2,输入值,提交; 

步骤3,刷新, (系统判定为重复提交,因为第2步,提交成功后, 系统移除了token ) 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/330283.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Druid-目前最好的连接池

转载自 Druid-目前最好的连接池 Druid是什么 Druid是阿里开源的连接池&#xff0c;是Java语言中最好的数据库连接池.Druid能够提供强大的监控和扩展功能&#xff0c;是为监控而生的数据库连接池&#xff01; GitHub&#xff1a;https://github.com/alibaba/druid/ 添加依赖 &l…

Nginx 部署 Vue 项目刷新页面出现404

问题 使用Vue.框架&#xff0c;利用vue-route编写了一个单页路由项目&#xff0c;运维协助在服务器端配置nginx。部署完成后&#xff0c;访问首页没问题&#xff0c;从首页里打开二级页面没问题&#xff0c;但是所有的二级页面打开后&#xff0c;再次刷新&#xff0c;就会出现…

repost: intro2token

repost 4 https://blog.csdn.net/Jason_Fangh/article/details/55113627 对于初学者来说&#xff0c;对Token和Session的使用难免会限于困境&#xff0c;开发过程中知道有这个东西&#xff0c;但却不知道为什么要用他&#xff1f;更不知道其原理&#xff0c;今天我就带大家一…

vue - resource 使用过程的坑

一. get 传参的坑&#xff1a;加params对象传参&#xff08;不能直接get(url, params)!!!&#xff09; this.$http.get(url, {params: { offset: this.offset, label: this.categray }})二. 使用post请求&#xff1a; 知识点 post参数的形式 form data(表单&#xff0c;通过url…

repo-关于URL编码

repost 4 http://www.ruanyifeng.com/blog/2010/02/url_encoding.html 一、问题的由来 URL就是网址&#xff0c;只要上网&#xff0c;就一定会用到。 一般来说&#xff0c;URL只能使用英文字母、阿拉伯数字和某些标点符号&#xff0c;不能使用其他文字和符号。比如&#xff0c…

Spring零配置之@Configuration注解详解

转载自 Spring零配置之Configuration注解详解 Configuration介绍 Spring3.0之前要使用Spring必须要有一个xml配置文件&#xff0c;这也是Spring的核心文件&#xff0c;而Spring3.0之后可以不要配置文件了&#xff0c;通过注解Configuration完全搞定。 Configuration即用来代替S…

session实现购物车

1、是什么&#xff1f; session 可以存储会话级变量&#xff0c;基于其实现购物车&#xff1b; 2、为什么&#xff1f; session是会话级变量&#xff0c;可以吧多次请求的数据串联起来&#xff0c;放到会话里&#xff1b; 3、怎么做&#xff1f; 【荔枝】转自 张孝祥 登录…

commons-logging,log4j,logback,slf4j之间的关系详解

转载自 commons-logging,log4j,logback,slf4j之间的关系详解commons-logging是apache最早提供的日志的门面接口。它的主要作用是提供一个日志门面&#xff0c;使用者可以使用不同的日志实现。用户可以自由选择第三方的日志组件作为具体实现&#xff0c;像log4j&#xff0c;或者…

Vue代理配置

在 package.json 的同级目录&#xff08;项目根目录&#xff09;下创建 vue.config.js在 vue.config.js 写入下列内容 module.exports {devServer: {proxy: http://localhost:8080}}这会告诉开发服务器将任何未知请求 (没有匹配到静态文件的请求) 代理到 http://localhost:40…

@Resource,@Autowired,@Inject3种注入方式详解

转载自 Resource,Autowired,Inject3种注入方式详解 概况 Resource,Autowired,Inject 这3种都是用来注入bean的&#xff0c;它们属于不同的程序中。 ANNOTATIONPACKAGESOURCEResourcejavax.annotationJava JSR-250Injectjavax.injectJava JSR-330Autowiredorg.springframework.b…

repost-微信小程序入门教程之一:初次上手

repost 4 http://www.ruanyifeng.com/blog/2020/10/wechat-miniprogram-tutorial-part-one.html 微信是中国使用量最大的手机 App 之一&#xff0c;日活跃用户超过3亿&#xff0c;月活跃用户超过11亿&#xff08;2019年底统计&#xff09;&#xff0c;市场极大。 2017年&#x…

Spring MVC : 概念模型 HandlerMethod(转载)

Spring MVC 应用启动时会搜集并分析每个 Web 控制器方法&#xff0c;从中提取对应的"<请求匹配条件,控制器方法>“映射关系&#xff0c;形成一个映射关系表保存在一个 RequestMappingHandlerMapping bean 中。然后在客户请求到达时&#xff0c;再使用 RequestMappin…

repo-话说软件详细设计工具

repost 4 https://blog.csdn.net/tang_huan_11/article/details/8043481 在软件设计是需要写软件详细说明书,设计此文档的时候,肯定少不了工具.现在我们就来了解一下软件详细设计的 工具. 1)程序流程图 程序流程图又称为程序框图,它是最古老,应用最广泛且最有争议描述详细设计的…

你必须了解Spring的生态

转载自 你必须了解Spring的生态 Spring不止是提供了IOC、AOP的功能&#xff0c;还提供了大量的基于Spring的项目&#xff0c;拿来用就行了&#xff0c;用于一站式开发&#xff0c;大大降低了开发的难度。 下面列举下主要的一些Spring的生态项目&#xff1a; Spring Boot&#…

Vue 使用 token

vue 解析 token 引入jwt-decode 包 npm install jwt-decode --save在 vue 中引入jwt-decode import jwtDecode from jwt-decodejs 中使用 const decode jwtDecode(token); console.log(decode);//解析后的对象vue-resource 设置请求头&#xff0c;带上token 第一种方法&a…

vmware安装centos6-步骤小结

【README】安装了很多次&#xff0c;但没有记录过&#xff0c;经常忘记&#xff0c;所以就记录一下 【1】 vm15 install centos8 at 2020/12/12 完成。

Ehcache介绍及整合Spring实现高速缓存

转载自 Ehcache介绍及整合Spring实现高速缓存 Ehcache介绍 EhCache 是一个纯Java的进程内缓存框架&#xff0c;具有快速、精干等特点&#xff0c;是Hibernate中默认的CacheProvider。它使用的是JVM的堆内存&#xff0c;超过内存可以设置缓存到磁盘&#xff0c;企业版的可以使用…

转:使用 Tkprof 分析 ORACLE 跟踪文件

【README】 昨天在验证oracle 数据库性能的时候&#xff0c;查询日志中 打出了 exec time , fetch time 不懂什么意思&#xff0c;所以就记录了下&#xff1b; A 表 680w&#xff0c; count 耗时5秒&#xff1b; B表 2013w&#xff0c; count 耗时10秒&#xff1b; A inne…

浅谈大型网站之负载均衡架构

转载自 浅谈大型网站之负载均衡架构 概念 负载均衡&#xff0c;英文名称为Load Balance&#xff0c;其意思就是分摊到多个操作单元上进行执行&#xff0c;例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等&#xff0c;从而共同完成工作任务。 负载均衡建立…

单词拆分

作者&#xff1a;xiao_ben_zhu 链接&#xff1a;https://leetcode-cn.com/problems/word-break/solution/shou-hui-tu-jie-san-chong-fang-fa-dfs-bfs-dong-tai/ 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 著作权归作者所有。商业转载请联系作者获得授权&#xff…