servlet防止表单重复提交

日常开发中,防表单重复提交是一项必须的工作

我们可以利用javascript防止表单重复提交,但是利用javascript防止表单重复提交会出现一个新的问题

因为某些用户可能会绕过script代码直接提交给服务器,这样就做不到防止表单重复提交了

所以我们要在服务器后端进行拦截

拦截的原理就是利用hidden这个隐藏域进行表单提交,并且hidden携带了服务器随机生成的字符串

我们可以把服务器端随机生成的字符串放入session作用域

这样,当我们进入servlet进行验证的时候就能取出我们随机生成的字符串

再和hidden提交过来的字符串进行比较

下面来看代码部分,首先是登录页面,我们需要进行一点处理,因为要生成一个随机字符串

我们利用servlet进行生成并且在jsp页面得到这个生成的随机字符串

看代码,这里利用TokenProsessor单例类生成

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

import sun.misc.BASE64Encoder;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@SuppressWarnings({ "serial", "restriction" })
public class FormServlet extends HttpServlet
{
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {
        HttpSession session = request.getSession();
        
        String token = TokenProcessor.getInstance().generateToken();
        
        session.setAttribute("token", token);
        
        request.getRequestDispatcher("/index.jsp").forward(request, response);
        
    }


    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {
        this.doGet(request, response);
    }

}

/**
 * 设置成单例类,降低产生的随机数的重复概率
 * @author Scorpion
 *
 */
class TokenProcessor
{
    private static TokenProcessor instance = new TokenProcessor();
    
    private TokenProcessor(){}
    
    public static TokenProcessor getInstance()
    {
        return instance;
    }
    
    @SuppressWarnings("restriction")
    public String generateToken()
    {
        Random random = new Random();
        String randomStr = System.currentTimeMillis() + random.nextInt(999999999) + "";
        try
        {
            MessageDigest md = MessageDigest.getInstance("md5");
            
            byte[] md5 = md.digest(randomStr.getBytes());
            
            BASE64Encoder encoder = new BASE64Encoder();
            return encoder.encode(md5);
            
        } catch (NoSuchAlgorithmException e)
        {
            throw new RuntimeException(e);
        }
        
    }
    
    
}

接下来跳转到jsp页面,下面是一个简单的表单,其中hidden中的value遍是我们生成的并且放到session作用域的随机字符串

<form action="/DoFormServlet" method="post">
    
    username:<input type="text" id="username" name="username"/></br>
    password:<input type="password" id="password" name="password"/><br>
    
    <input type="hidden" value="${token}" id="token" name="token"/>
    <input type="submit" value="submit"/>
    </form>

表单提交后再把流程转到DoFormServlet

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;

@SuppressWarnings("serial")
public class DoFormServlet extends HttpServlet
{
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException
    {
        
        String username = req.getParameter("username");
    
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");
        
        PrintWriter out = resp.getWriter();
        
        boolean b = isToken(req);
        if(!b)
        {
            out.write("请不要重复提交表单");
            return;
        }
        
        req.getSession().removeAttribute("token");
        
        out.write("欢迎你:" + username);    
    }
    
    private boolean isToken(HttpServletRequest req)
    {
        String client_token = req.getParameter("token");
        if(client_token==null){
            return false;
        }
        
        String server_token = (String) req.getSession().getAttribute("token");
        if(server_token==null){
            return false;
        }
        
        if(!client_token.equals(server_token)){
            return false;
        }
        
        return true;
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException
    {
        this.doPost(req, resp);
    }
}

至此,本例完成。。。

原文地址:https://www.cnblogs.com/withscorpion/p/5651418.html