使用session防止表单进行重复提交

我们都知道可以通过js的方法来实现防止表单重复提交,但是js只适用于“在网络延迟的情况下让用户有时间点击多次submit按钮导致表单重复提交” 的情况下进行操作,

那如果碰到“表单提交后用户点击【刷新】按钮导致表单重复提交”和“用户提交表单后,点击浏览器的【后退】按钮回退到表单页面后进行再次提交”的场景下JS就显得心有余而力不足了,这个时候我们可以通过java当中生成token验证token来实现防止表单提交;

先看一下我的项目结构:

我们用到的只有这四个页面,其他的可以忽略

首先先来看一下创建token的servlet,tokenDemo.java:

package session;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "TokenDemo",urlPatterns = {"/session/TokenDemo"})
public class TokenDemo extends HttpServlet {
    private static final long serialVersionUID =  -884689940866074733L;
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String token = TokenProccessor .getInstance().makeToken();//创建令牌
//        System.out.print("生成的令牌token是"+token);
        request.getSession().setAttribute("token",token); //存到session里面
        request.getRequestDispatcher("/token.jsp").forward(request,response);
    }
}

  这里面有一个生成token的类,叫做TokenProccessor,接下来我们看看token是怎么生成的,

TokenProccessor .java:
package session;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

import sun.misc.BASE64Encoder;

public class TokenProccessor {
    private TokenProccessor() {}

    ;
    private static final TokenProccessor instance = new TokenProccessor();

    public static TokenProccessor getInstance() {
        return instance;
    }

    //生成token
    public String makeToken(){
        String token = (System.currentTimeMillis() + new Random().nextInt(999999999)) + "";
        try{
            MessageDigest md = MessageDigest.getInstance("md5");
            byte md5[] = md.digest(token.getBytes());
            BASE64Encoder encoder = new BASE64Encoder();
            return encoder.encode(md5);
        }catch(NoSuchAlgorithmException e){
            throw new RuntimeException(e);
        }
    }

}

  好,我们现在有了token,我们可以在页面上去使用它:token.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>token</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/session/ResultToken" method="post">
    <%--使用隐藏存储生成token--%>

    <input type="hidden" name="token" value="${token}">
    用户名:<input type="text" name="username">
    <input type="submit" value="提交">

</form>

</body>
</html>

  我们接下来应该干嘛呢,对,当然是要进行表单的验证啦,resultToken.java:

package session;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "ResultToken", urlPatterns = {"/session/ResultToken"})
public class ResultToken extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=utf-8");
        boolean b = isRepeatSubmit(request); //判断用户是否重复提交;
        if (b == true) {
            response.getWriter().println("请不要重复提交");
            return;
        }
        request.getSession().removeAttribute("token");
        response.getWriter().println("处理用户提交请求");
    }

    /***
     * 判断用户提交上来的token和服务器生成的token是否一致
     * true:重复提交了
     *false:没有重复提交
     * */
    private boolean isRepeatSubmit(HttpServletRequest request) {
        String client_token = request.getParameter("token");
        //如果用户提交的没有token,那么用户则是重复提交了表单
        if (client_token == null) {
            return true;
        }
        //取出session中的token
        String server_token = (String) request.getSession().getAttribute("token");
        //如果哦用户的session里面不存在Token,则用户重复提交了表单
        if (server_token.equals(client_token)) {
            return true;
        }
        return false;
    }
}

  ok,记得写完servlet的时候必须要去web.xml配置一下,不然取不到路径。所有的登录都需要来验证token。

 

posted @ 2018-05-18 11:17  明明一颗大白菜  阅读(1147)  评论(0编辑  收藏  举报
<-- -->