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

解决思路:

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

具体的做法:

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

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

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

代码实现:

  • form.html


  
    form.html
    
    
    

    


   
      
    
用户名:
  • 负责产生表单的servlet
    这里随机数产生器类TokenProccessor{}请看全局随机数生成器的设计
//负责产生表单
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("
"); out.write(""); out.println("用户名:"); out.println(""); out.println("
"); } 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);
    }

}

你可能感兴趣的:(服务器端使用Session来防止表单重复提交)