服务器端使用Session来防止表单重复提交

解决思路:

  • 表单不能由HTML页面输出,须有程序生成输出
  • 程序输出表单时需在表单里添加一个随机数打给浏览器
  • 用户提交表单时把这个随机数带给服务器程序
  • 用户带过来的随机数和服务器随机数进行比较,若一致则接受,否则不予接受

具体的做法:

在服务器端生成一个唯一的随机标识号,专业术语称为Token(令牌),同时在当前用户的Session域中保存这个Token。然后将Token发送到客户端的Form表单中,在Form表单中使用隐藏域来存储这个Token,表单提交的时候连同这个Token一起提交到服务器端,然后在服务器端判断客户端提交上来的Token与服务器端生成的Token是否一致,如果不一致,那就是重复提交了,此时服务器端就可以不处理重复提交的表单。如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。

在下列情况下,服务器程序将拒绝处理用户提交的表单请求:

  • 存储Session域中的Token(令牌)与表单提交的Token(令牌)不同。
  • 当前用户的Session中不存在Token(令牌)。
  • 用户提交的表单数据中没有Token(令牌)。

代码实现:

  • form.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>form.html</title>
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="this is my page">
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">

    <script type="text/javascript">
        var isCommitted = false;
        function dosubmit()
        {
            if(isCommitted==false){
                isCommitted = true;
                return true;
            }else{
                return false;
            }
                
        }
        function dosubmit(){
            var submit = document.getElementById("submit");
            submit.disabled= "disabled";
            return true;
        
        }
    </script>


  </head> 
  <body>    
    <form action="~这里是你表单提交的servlet路径~/FormServlet" method="post" onsubmit="return dosubmit()">
        用户名:<input type="text" name="username">
        <input type="submit" value="提交" id="submit">
    </form>
  </body>
</html>

//负责产生表单
public class FormServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        
        String token = TokenProccessor.getInstance().makeToken();
        request.getSession().setAttribute("token", token);  //在服务器端保存随机数
        
        out.println("<form action='/day07/servlet/DoFormServlet' method='post'>");
            out.write("<input type='hidden' name='token' value='"+token+"'>");
            out.println("用户名:<input type='text' name='username'>");
            out.println("<input type='submit' value='提交'>");
        out.println("</form>");
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        doGet(request, response);
    }
}
  • 表单提交处理,如果不是不是重复提交则进行处理
public class DoFormServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        
        boolean b = isToken(request);  //判断用户是否是重复提交
        if(b==true){
            System.out.println("请不要重复提交");
            return;
        }
        
        request.getSession().removeAttribute("token");//移除session中的token
        
        System.out.println("处理用户提交请求!!");
        
    }

  /**
         * 判断客户端提交上来的令牌和服务器端生成的令牌是否一致
         * @param request
         * @return 
         *         true 用户重复提交了表单 
         *         false 用户没有重复提交表单
         */

    private boolean isToken(HttpServletRequest request) {
        
        String client_token = request.getParameter("token");
        //1、如果用户提交的表单数据中没有token,则用户是重复提交了表单
        if(client_token==null){
            return true;
        }
        //取出存储在Session中的token
        String server_token = (String) request.getSession().getAttribute("token");
        //2、如果当前用户的Session中不存在Token(令牌),则用户是重复提交了表单
        if(server_token==null){
            return true;
        }
        //3、存储在Session中的Token(令牌)与表单提交的Token(令牌)不同,则用户是重复提交了表单
        if(!client_token.equals(server_token)){
            return true;
        }
        
        return false;
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        doGet(request, response);
    }

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表...
    重山杨阅读 1,760评论 5 26
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,853评论 18 139
  • 具体的做法:在服务器端生成一个唯一的随机标识号,专业术语称为Token(令牌),同时在当前用户的Session域中...
    大虾咪阅读 236评论 0 0
  • 原则,少而精。 形式∶面授、借力他人和小团体座谈。 成果∶让自己值钱 1.马捷克,二校六(4)班。小萍同学的儿子。...
    行一馆阅读 355评论 0 0
  • 1.专注一件重要的事 如何判断一件事情是不是很重要?就看它是不是在你人生当中是不可缺少的,是不是解决了这个问题,其...
    好听的暖阳阅读 220评论 2 3