客户端和服务器端防表单重复提交的策略

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


1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  

2 <html>  

3 <head>  

4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  

5 <title>Insert title here</title>  

6 <script type="text/javascript">  

7 /*  

8  var isCommit = false;  

9  function doSubmit(){  

10     if(! isCommit){  

11     isCommit = true;  

12         return true;  

13     }   else{  

14     return false;  

15     }  

16  }*/  

17  function doSubmit(){//使提交按钮再提交完成后不可用  

18     var input = document.getElementById("submit");  

19     input.disabled='disabled';  

20     return true;  

21  }  

22 </script>  

23   

24   

25 </head>  

26 <body>  

27 <form action="/Web/servlet/DoFormServlet" method="post" οnsubmit="return doSubmit()">  

28 用户名:<input type="text" name="username"><br>  

29 <input id="submit" type="submit" value="提交" >  

30 </form>  

31 </body>  

32 </html>  


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


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

首先是产生表单的Servlet

[java] view plaincopyprint?

33 package com.bird.form;  

34   

35 import java.io.IOException;  

36 import java.security.MessageDigest;  

37 import java.security.NoSuchAlgorithmException;  

38 import java.util.Random;  

39   

40 import javax.servlet.ServletException;  

41 import javax.servlet.http.HttpServlet;  

42 import javax.servlet.http.HttpServletRequest;  

43 import javax.servlet.http.HttpServletResponse;  

44   

45 import sun.misc.BASE64Encoder;  

46   

47 public class FormServlet extends HttpServlet {  

48   

49     /** 

50      * 写给浏览器一个表单,并且防止多次重复提交而创建随机数 

51      * @author Bird 

52      */  

53     private static final long serialVersionUID = 1L;  

54   

55     public void doGet(HttpServletRequest request, HttpServletResponse response)  

56             throws ServletException, IOException {  

57         //产生随机数(表单号 )  

58         TokenProcessor tp = TokenProcessor.getInstance();  

59         String token = tp.generateToken();  

60           

61         request.getSession().setAttribute("token", token);  

62           

63         request.getRequestDispatcher("/form.jsp").forward(request, response);  

64     }  

65   

66     public void doPost(HttpServletRequest request, HttpServletResponse response)  

67             throws ServletException, IOException {  

68         doGet(request, response);  

69   

70     }  

71   

72 }  

73   

74 class TokenProcessor{//令牌发生器   

75     /** 

76      * 1.把构造方法私有 

77      * 2.自己创建一个 

78      * 3.对外暴露一个方法,允许获得创建的对象 

79      */  

80       

81     private TokenProcessor(){}  

82       

83     private static final TokenProcessor instance = new TokenProcessor();  

84       

85     public static TokenProcessor getInstance(){  

86         return instance;  

87     }  

88       

89     public String generateToken(){//获取唯一的表单码  

90         String token = System.currentTimeMillis() + new Random().nextInt() + "";  

91         try {  

92             MessageDigest md5 = MessageDigest.getInstance("md5");  

93             byte[] md = md5.digest(token.getBytes());  

94               

95             //base64进行编码  

96             BASE64Encoder encoder = new BASE64Encoder();  

97             return encoder.encode(md);  

98         } catch (NoSuchAlgorithmException e) {  

99             throw new RuntimeException(e);  

100         }  

101     }  

102 }  


然后是那个JSP页面

[java] view plaincopyprint?

103 <%@ page language="java" contentType="text/html; charset=UTF-8"  

104     pageEncoding="UTF-8"%>  

105 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  

106 <html>  

107 <head>  

108 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  

109 <title>Insert title here</title>  

110 </head>  

111 <body>  

112     <form action="/Web/servlet/DoFormServlet" method="post">  

113     <input type="hidden" name="token" value="${token}">  

114     用户名:<input type="text" name="username"><br/>  

115     <input type="submit" value="提交">  

116     </form>  

117 </body>  

118 </html>  


然后是处理提交请求的Servlt

[java] view plaincopyprint?

119 package com.bird.form;  

120   

121 import java.io.IOException;  

122   

123 import javax.servlet.ServletException;  

124 import javax.servlet.http.HttpServlet;  

125 import javax.servlet.http.HttpServletRequest;  

126 import javax.servlet.http.HttpServletResponse;  

127   

128 public class DoFormServlet extends HttpServlet {  

129   

130     /** 

131      * 处理表单的重复提交 

132      * @author Bird 

133      */  

134     private static final long serialVersionUID = 1L;  

135   

136     public void doGet(HttpServletRequest request, HttpServletResponse response)  

137             throws ServletException, IOException {  

138         boolean b = isTokenValue(request);  

139         if(!b){  

140             System.out.println("请不要重复提交");  

141             return;  

142         }  

143         request.getSession(false).removeAttribute("token");  

144         System.out.println("向数据库中注入数据");  

145     }  

146   

147     private boolean isTokenValue(HttpServletRequest request) {  

148         String clinet_token = request.getParameter("token");  

149         if(clinet_token == null){  

150               

151             return false;  

152         }  

153         String server_token = (String) request.getSession(false).getAttribute("token");  

154         if(server_token == null){  

155               

156             return false;  

157         }  

158         if(!server_token.equals(clinet_token)){  

159               

160             return false;  

161         }  

162           

163         return true;  

164     }  

165   

166     public void doPost(HttpServletRequest request, HttpServletResponse response)  

167             throws ServletException, IOException {  

168         doGet(request, response);  

169   

170     }  

171   

172 }  



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值