• 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);
        }
    }

    至此,本例完成。。。

  • 相关阅读:
    Linux 下编译Android-VLC开源播放器详解(附源码下载)
    VC/Wince 实现仿Win8 Metro风格界面2——页面滑动切换(附效果图)
    Android Launcher分析和修改3——Launcher启动和初始化
    VC/Wince 实现仿Win8 Metro风格界面1——设计概述和自绘Button(附效果图)
    Android Launcher分析和修改2——Icon修改、界面布局调整、壁纸设置
    Android Launcher分析和修改1——Launcher默认界面配置(default_workspace)
    WARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 8
    编程工具系列之二------使用GDB的源代码查看功能
    编程工具系列之一------使用GDB的堆栈跟踪功能
    unable to open sync connection
  • 原文地址:https://www.cnblogs.com/withscorpion/p/5651418.html
Copyright © 2020-2023  润新知