客户端防表单重复提交和服务器端session防表单重复提交

来源:互联网 发布:逆战天王宏数据 编辑:程序博客网 时间:2024/05/18 00:01

   为了防止用户在客户端重复提交表单,要分析从客户端和服务端对重复提交的表单就行处理,首先是客户端处理重复提交表单,使用JavaScript方法,第一种是只允许表单提交一次,后来的不能再提交,第二种是提交一次后按钮变成不可用,下面是代码的实现

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title><script type="text/javascript">/* var isCommit = false; function doSubmit(){ if(! isCommit){ isCommit = true; return true; }else{ return false; } }*/ function doSubmit(){//使提交按钮再提交完成后不可用 var input = document.getElementById("submit"); input.disabled='disabled'; return true; }</script></head><body><form action="/Web/servlet/DoFormServlet" method="post" onsubmit="return doSubmit()">用户名:<input type="text" name="username"><br><input id="submit" type="submit" value="提交" ></form></body></html>

但是仅仅在客户端进行处理是远远不够的,这叫只能防的了君子防不了小人,因为可以根据服务器的提交地址自己写一个表单或者去掉JavaScript代码进行自己的提交,这样仍旧无法阻止客户端的表单的重复提交,下面就需要在服务端做手脚,首先需要写一个Servlet用来产生表单,他的想法是产生一个唯一的Id ,通过随机数才产生,然后付到表单上,当表单提交的时候,根据验证这个ID号来判断时候是重复提交表单。


当然,这个随即数的产生不简单,首先使用单例设计模式,减少随机数产生的相似性概率,然后使用当前时间毫秒数加上一个随机数来进行,然后因为这样产生的随机数大小长度不等,所以进行md5编码后再进行BASE64编码,产生长度相等的而且字符都是键盘上可以识别的随机数,放到表单的隐藏域里面去。这个BASE64编码在网络传输中也有很好的作用,表单提交后,处理的Servlet根据放入到Session中的随机数来验证是不是重复提交,如果不是,就进行下面的比如放入到数据库等操作,如果是,则回复请求,说明表单重复提交。下面上代码

首先是产生表单的Servlet

package com.bird.form;import java.io.IOException;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.util.Random;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import sun.misc.BASE64Encoder;public class FormServlet extends HttpServlet {/** * 写给浏览器一个表单,并且防止多次重复提交而创建随机数 * @author Bird */private static final long serialVersionUID = 1L;public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {//产生随机数(表单号 )TokenProcessor tp = TokenProcessor.getInstance();String token = tp.generateToken();request.getSession().setAttribute("token", token);request.getRequestDispatcher("/form.jsp").forward(request, response);}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}class TokenProcessor{//令牌发生器 /** * 1.把构造方法私有 * 2.自己创建一个 * 3.对外暴露一个方法,允许获得创建的对象 */private TokenProcessor(){}private static final TokenProcessor instance = new TokenProcessor();public static TokenProcessor getInstance(){return instance;}public String generateToken(){//获取唯一的表单码String token = System.currentTimeMillis() + new Random().nextInt() + "";try {MessageDigest md5 = MessageDigest.getInstance("md5");byte[] md = md5.digest(token.getBytes());//base64进行编码BASE64Encoder encoder = new BASE64Encoder();return encoder.encode(md);} catch (NoSuchAlgorithmException e) {throw new RuntimeException(e);}}}

然后是那个JSP页面

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body><form action="/Web/servlet/DoFormServlet" method="post"><input type="hidden" name="token" value="${token}">用户名:<input type="text" name="username"><br/><input type="submit" value="提交"></form></body></html>

然后是处理提交请求的Servlt

package com.bird.form;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class DoFormServlet extends HttpServlet {/** * 处理表单的重复提交 * @author Bird */private static final long serialVersionUID = 1L;public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {boolean b = isTokenValue(request);if(!b){System.out.println("请不要重复提交");return;}request.getSession(false).removeAttribute("token");System.out.println("向数据库中注入数据");}private boolean isTokenValue(HttpServletRequest request) {String clinet_token = request.getParameter("token");if(clinet_token == null){return false;}String server_token = (String) request.getSession(false).getAttribute("token");if(server_token == null){return false;}if(!server_token.equals(clinet_token)){return false;}return true;}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}


原创粉丝点击