`
ydbc
  • 浏览: 711572 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

JSP学习之------>客户端防表单重复提交和服务器端session防表单重复提交

 
阅读更多

1.什么叫表单重复提交:

所谓表单重复提交,是指用户通过多次点击提交按钮或多次刷新表单提交页面等造成用户表单重复提交的现象

2.表单重复提交有哪些情况:

(1)用户在程序提交表单的时间段里多次提交表单
(2)重复刷新提交后的表单
(3)用户点击浏览器回退按钮,然后再次提交

3.如果解决表单重复提交:

(1)方法1:客户端防表单重复提交: 一般通过js代码防止第一种情况的发生,对于第二种和第三种的情况很难避免,并且稍微有经验的用户可以通过去掉页面js生成自己的html页面来访问服务器,这样客户端的防表单重复提交只能“防君子不能防小人”,并且可以增强用户体验感。


(2)方法2:服务器端session防表单重复提交:一般是利用令牌的原理来实现表单重复提交的,具体做法:

A. 对于用户每一次访问表单页面,均先经过CreateFormServlet的Servlet,其作用是在跳转表单页面之前,由BASE64Encoder类生成一个唯一的字符串,即表单号,并保存在session域中.

B.然后用户提交表单时,带着表单号,先验证客户端提交过来的表单号和session域中的表单号是否相同,如果不同则证明是重复提交,如果相同,则证明是第一次提交,并将表单号从session域中移除。

4.例子程序:

regist.jsp

  1. <%@ page language="java"import="java.util.*"pageEncoding="utf-8"%>
  2. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  3. <html>
  4. <scripttype="text/javascript">
  5. /*虽然客户端防表单重复提交,有很多漏洞,但是为了提高客户体验感,一把是客户端和服务器配合防表单重复提交,
  6. 客户端防重复提交的漏洞:1.客户复制源代码,去掉此js脚本,生成自己的html页面,然后提交
  7. 2.重复刷新提交后的表单
  8. 3.用户点击浏览器回退按钮,然后再次提交
  9. 客户端防重复提交的代码:
  10. 1.方法1:
  11. var isCommited =false;
  12. function dosubmit(){
  13. if(!isCommited){
  14. isCommited = true;
  15. return true;
  16. }else{
  17. return false;
  18. }
  19. }
  20. */
  21. //或者使"注册"按钮点击一次后不可用
  22. function dosubmit1(){
  23. var input = document.getElementById("submit");
  24. input.disabled="disabled";
  25. return true;
  26. }
  27. </script>
  28. <body>
  29. <formaction="/CookieAndSession/servlet/regist"method="post"onsubmit="return dosubmit()">
  30. 用户名:<inputtype="text"name="username"value="aaa"><br/>
  31. <inputtype="hidden"name="c_token"value="${token}">
  32. <inputid="submit"type="submit"value="注册">
  33. </form>
  34. </body>
  35. </html>
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
 <script type="text/javascript">
    /*虽然客户端防表单重复提交,有很多漏洞,但是为了提高客户体验感,一把是客户端和服务器配合防表单重复提交,
              客户端防重复提交的漏洞:1.客户复制源代码,去掉此js脚本,生成自己的html页面,然后提交
                           2.重复刷新提交后的表单
                           3.用户点击浏览器回退按钮,然后再次提交
     
             客户端防重复提交的代码:
       1.方法1:
	     var isCommited = false;
	     function dosubmit(){
	        if(!isCommited){
	            isCommited = true;
	            return true;
	        }else{
	            return false;
	        }
	     }
     */
     
     //或者使"注册"按钮点击一次后不可用
	     function dosubmit1(){
	        var input = document.getElementById("submit");
	        input.disabled="disabled";
	        return true;
	     }
  </script>
  <body>
         <form action="/CookieAndSession/servlet/regist" method="post" onsubmit="return dosubmit()">
             用户名:<input type="text" name="username" value="aaa"><br/>
             <input type="hidden" name="c_token" value="${token}">
             <input id="submit" type="submit" value="注册" >
         </form>
   </body>
</html>
CreateFormServlet.java url-pattern: /servlet/createform

  1. package edu.form;
  2. import java.io.IOException;
  3. import java.security.MessageDigest;
  4. import java.security.NoSuchAlgorithmException;
  5. import java.util.Random;
  6. import javax.servlet.ServletException;
  7. import javax.servlet.http.HttpServlet;
  8. import javax.servlet.http.HttpServletRequest;
  9. import javax.servlet.http.HttpServletResponse;
  10. import sun.misc.BASE64Encoder;
  11. public class CreateFormServletextends HttpServlet {
  12. public void doGet(HttpServletRequest request, HttpServletResponse response)
  13. throws ServletException, IOException {
  14. //产生表单号
  15. String token = TokenProcessor.getInstance().generateToken();
  16. request.getSession().setAttribute("token", token);
  17. request.getRequestDispatcher("/regist.jsp").forward(request, response);
  18. }
  19. public void doPost(HttpServletRequest request, HttpServletResponse response)
  20. throws ServletException, IOException {
  21. doGet(request, response);
  22. }
  23. }
  24. class TokenProcessor{
  25. private static TokenProcessor token =new TokenProcessor();
  26. private TokenProcessor(){}
  27. public static TokenProcessor getInstance(){
  28. return token;
  29. }
  30. public String generateToken(){
  31. String token = System.currentTimeMillis()+new Random().nextInt()+"";
  32. try {
  33. MessageDigest md = MessageDigest.getInstance("md5");
  34. byte[] md5 = md.digest(token.getBytes());
  35. //base64编码
  36. BASE64Encoder encoder = new BASE64Encoder();
  37. return encoder.encode(md5);
  38. } catch (NoSuchAlgorithmException e) {
  39. throw new RuntimeException(e);
  40. }
  41. }
  42. }
package edu.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 CreateFormServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
        //产生表单号
		String token = TokenProcessor.getInstance().generateToken();
		request.getSession().setAttribute("token", token);
		request.getRequestDispatcher("/regist.jsp").forward(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
         doGet(request, response);
	}
	
}
class TokenProcessor{
	private static TokenProcessor token = new TokenProcessor();
	private TokenProcessor(){}
	public static TokenProcessor getInstance(){
		return token;
	}
	public String generateToken(){
		String token = System.currentTimeMillis()+new Random().nextInt()+"";
		try {
			MessageDigest md = MessageDigest.getInstance("md5");
			byte[] md5 = md.digest(token.getBytes());
			//base64编码
			BASE64Encoder encoder = new BASE64Encoder();
			return encoder.encode(md5);
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
	}
	
}
RegistServlet.java url-pattern: /servlet/regist
  1. package edu.form;
  2. import java.io.IOException;
  3. import java.io.PrintWriter;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. public class RegistServletextends HttpServlet {
  9. public void doGet(HttpServletRequest request, HttpServletResponse response)
  10. throws ServletException, IOException {
  11. response.setCharacterEncoding("utf-8");
  12. response.setContentType("text/html;charset=utf-8");
  13. PrintWriter out = response.getWriter();
  14. boolean isValid = tokenValidate(request);
  15. if(!isValid){
  16. out.print("<script>alert('请不要重复提交,程序正在处理!');</script>");
  17. return ;
  18. }
  19. out.println("正在向数据库注册用户信息!");
  20. }
  21. private boolean tokenValidate(HttpServletRequest request) {
  22. String c_token = request.getParameter("c_token");
  23. String s_token = (String) request.getSession().getAttribute("token");
  24. //防止用户自定义html
  25. if(c_token==null)
  26. return false;
  27. if (s_token==null)
  28. return false;
  29. if (!s_token.equals(c_token))
  30. return false;
  31. request.getSession().removeAttribute("token");
  32. return true;
  33. }
  34. public void doPost(HttpServletRequest request, HttpServletResponse response)
  35. throws ServletException, IOException {
  36. doGet(request, response);
  37. }
  38. }
package edu.form;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class RegistServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
        boolean isValid = tokenValidate(request); 
        if(!isValid){
           out.print("<script>alert('请不要重复提交,程序正在处理!');</script>");
           return ; 	
        }
        out.println("正在向数据库注册用户信息!");
        
	}

	private boolean tokenValidate(HttpServletRequest request) {
         String c_token = request.getParameter("c_token");
         String s_token = (String) request.getSession().getAttribute("token");
         //防止用户自定义html
		 if(c_token==null)
			 return false;
		 if (s_token==null) 
			return false;
         if (!s_token.equals(c_token)) 
			return false;
         request.getSession().removeAttribute("token");
	     return true;
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
         doGet(request, response);
	}
}
程序不能直接进入regist.jsp页面,只能通过http://localhost:8080/CookieAndSession/servlet/createform进入CreateFormServlet.java通过此Servlet跳转至注册页面

此时http://localhost:8080/CookieAndSession/servlet/createform页面原代码如下:


这样就可以解决以上三种可能出现的表单重复提交问题!

分享到:
评论

相关推荐

    JSP针对表单重复提交的处理方法

    主要介绍了JSP针对表单重复提交的处理方法,涉及JSP基于session的重复提交判定使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下

    servlet和jsp学习指南

    《Servlet和JSP学习指南》是系统学习Servlet和JSP的必读之作。由全球知名的Java技术专家(《HowTomcat Works》作者)亲自执笔,不仅全面解读Servlet和JSP的最新技术,重点阐述JavaWeb开发的重要编程概念和设计模型,...

    jsp-.rar_flag提交

    jsp防止重复提交 这做最好结合让jsp页面过期一起用。当用户返回到上一表单页面时(按backspase键、返回按钮,右击--返回),让表单页面过期。这样才可以让用户主动的刷新jsp而从新生成一个session.setAttribute(...

    jsp页面间通过request/session传值

    例1:jsp页面间通过request/session传值 session1.jsp(从表单输入usernmae,将该参数传递到session2.jsp)

    JSP避免Form重复提交的三种方案

    1 javascript ,设置一个变量,只允许提交一次。 [removed] var checksubmitflg = false; function checksubmit() { if (checksubmitflg == true) { return false; } checksubmitflg = true; return true; } ...

    regedit.jsp 表单注册用户名密码

    &lt;jsp:useBean id="query" class="Bean.QueryBean" scope="session"&gt; &lt;jsp:setProperty name="query" property="*"/&gt; &lt;/jsp:useBean&gt; &lt;html&gt; &lt;body&gt; request.setCharacterEncoding("UTF-8"); String name=request....

    JSP期末考试试卷及参考答案

    7、在JSP内置对象中,(request)对象是从客户端向服务器端发出请求,包括用户提交的信息以及客户端的一些信息,此对象的(getparameter)方法可以获取客户端表单中某输入框提交的信息。 8、在JSP内置对象中,(response)...

    jsp编程技巧集锦

    数字转中文&lt;br&gt;128 自动计算金额&lt;br&gt;129 JSP页面打印中使用WebBrowser控件&lt;br&gt;130 &lt;select...&gt;不刷新页面添加新的类别&lt;br&gt;131 鼠标滚动缩放图片&lt;br&gt;132 根据输入的表名生成输入数据表格&lt;br&gt;133 JSP表格输出到Excel...

    JSP Session

    JSP Session HTTP是无状态协议,这意味着每次客户端检索网页时,都要单独打开一个服务器连接,因此服务器不会记录下先前客户端请求的任何信息。 有三种方法来维持客户端与服务器的会话: Cookies 网络服务器...

    JavaWeb实验报告(1).pdf

    (1)inputName.jsp 的具体要求 该页面有一个表单,用户通过该表单输入自己的姓名并提交给 people.jsp 页面。 (2)people.jsp 的具体要求 JSP 页面有名字为 person、类型是 StringBuffer 以及名字是 count,类型为...

    Ajax请求session超时处理流程

    java服务器端处理: SessionValidateFilter中修改: if (ServerInfo.isAjax(request)) { request.setAttribute("statusCode", 301); request.setAttribute("message", "Session timeout!"); response....

    Java学习笔记

    Java学习笔记 1、连接数据库步骤 2、不同数据库的驱动程序和连接字符串 ...11、避免表单重复提交的技术 12、表单的GET和POST方法的区别 13、使用HttpServletRequest对象获得更多客户端信息 14、JSP实现多数据分页

    JSP实例编程100例

    23、&lt;c:set&gt;和&lt;c:remove&gt; 的用法 24、&lt;c:import&gt; 的用法 25、jsp-include的用法 26、汉字处理 27、网页重定向 28、自动更新网页 29、存取session 30、&lt;c:redirect&gt; 的用法 31、单选型列表框 32、jsp文件中定义类 33...

    jsp 重复提交问题

    看了网上的,有几种方法: 1 在你的表单页里HEAD区加入这段代码: 代码如下:&lt... 2 生成一个令牌保存在用户session中,在form中加一个hidden域,显示该令 牌的值,form提交后重新生成一个新的令牌,将用户提交的令牌和

    JSP实用技巧集合,jsp编程的一些小技巧总结

    103.使用session对象防止表单重复提交? 104.获取用户真实IP地址? 105.获取请求中的所有参数? 106.获取完整的请求URL? 107.在重新显示表单时保留用户已经输入的合法数据? 108.使用选代器遍历集合 109.使用特定字符串...

    用户登录Demo(JSP+Servlet)

    &gt; login.jsp:提供登录表单,提交表单请求LoginServlet &gt; LoginServlet:获取请求参数,校验用户是否登录成功 &lt;&gt; 失败:保存错误信息到request域,转发到login.jsp(login.jsp显示request域中的错误信息) &lt;&gt; 成功...

    教学、学习必备:jsp教案

    2.1.1理解服务器端执行 17 2.1.2JSP页面的基本结构 17 2.1.3JSP的运行原理 18 2.1.4JSP页面的成员变量和方法 18 2.1.5JSP代码 19 2.1.6 Java程序片 20 2.1.7Java表达式 22 2.1.8JSP中的注释 23 2.2HTML基础 24 2.2.1...

Global site tag (gtag.js) - Google Analytics