使用Token(令牌),解决表单重复提交的问题

  在做项目或者做一些小程序开发的过程中,有可能会遇到表单重复提交的问题。那么在什么情况下会出现表单的重复提交的问题呢?第一:刷新页面的时候有可能出现重复提交表单,异步提交不会出现这种问题。第二:页面跳转,也有可能出现重复提交。比如用户新增后再刷新页面,然后,这样就很容易出现重复提交。一旦用户刷新页面,表单就会再次提交。异步提交可以避免表单的重复提交的问题。
当我们刷新页面的时候,就会出现以下这个问题
在这里插入图片描述
  如何解决表单重复提交的问题呢?在当前用户的Session域中保存Token(令牌),然后将生成的Token发送到客户端的Form表单中。在Form表单中使用隐藏域来存储Token,表单提交的时间连同Token一起提交到服务器端,然后在服务器端判断客户端提交过来的Token与服务器端生成的Token是否一致。如果不一致,那就是Form表单重复提交;如果相同则处理表单提交,处理完后清除当前用户的Session域中储存的Token。

理解图:

在这里插入图片描述
在一下的几种情况下,服务器会拒绝处理用户提交的表单请求:
1、 存储Session域中的Token(令牌)与表单提交的Token不同。
2、 当前用户的Session中不存在Token。
3、 用户提交的表单数据中没有Token。

封装的类

package com.gx.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
import sun.misc.BASE64Encoder;
public class TokenProccessor {
	/*
     *单例设计模式(保证类的对象在内存中只有一个)
     *1、把类的构造函数私有
     *2、自己创建一个类的对象
     *3、对外提供一个公共的方法,返回类的对象
     */
    private TokenProccessor(){}
    private static final TokenProccessor instance = new TokenProccessor();
    public static TokenProccessor getInstance(){
        return instance;
    }
    public String makeToken(){  //checkException
        //  7346734837483  834u938493493849384  43434384   //获取单前时间再加上随机数
        String token = (System.currentTimeMillis() + new Random().nextInt(999999999)) + "";
        //数据指纹   128位长   16个字节  md5
        try {
        	//java.security.MessageDigest 类用于为应用程序提供信息摘要算法的功能
            MessageDigest md = MessageDigest.getInstance("md5");
            byte md5[] =  md.digest(token.getBytes());
            //base64编码--任意二进制编码明文字符   adfsdfsdfsf
            BASE64Encoder encoder = new BASE64Encoder();
            return encoder.encode(md5);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }
}

Jsp的核心代码如下:

 <body>
<form action="${ctx}/servlet/LoginServlet" method="post">
     <!--    通过EL表达式获取session中的token值 -->
    	<input type="hidden" name="token" value="${token}"/>
<!--    通过session表达式获取token的值 -->
<!-- <input type="hidden" name="token" value="<%=session.getAttribute("token") %>"> -->
    	<table>
    	<tr>
    	<td>用户名:</td>
<td><input type="text" name="name"/></td>
    	</tr>
    	<tr>
    	<td>密码:</td>
    		<td><input type="password" name="password"/></td>
    	</tr>
    	<tr>
    		<td>验证码:</td>
    	<td><input type="text" name="codekey"/></td>
    	</tr>
    	<tr>
    		<td>
    		<img id="codekey" alt="" src="${ctx}/servlet/IdentityServlet?t=${now}" onclick="refcodekey()"></td>
    	</tr>
    	<tr>
    	<td>
    		<input type="submit" value="登录"/>
    	</td>
    	</tr>
    	</table>
    </form>
    <script type="text/javascript">
    	function refcodekey(){
         document.getElementById("codekey").src="${ctx}/servlet/IdentityServlet?t="+new Date();
        }
    </script>
  </body>

Servlet的核心代码:

  public void toLogin(HttpServletRequest request, HttpServletResponse response)
	throws ServletException, IOException {
	String token = TokenProccessor.getInstance().makeToken();//获取token值
	request.getSession().setAttribute("token", token);//把token值保存到session中
request.getRequestDispatcher("/jsp/login.jsp").forward(request, response);//页面跳转
	}
public void login(HttpServletRequest request, HttpServletResponse response)
	throws ServletException, IOException {
      //获取页面的值
	String name=request.getParameter("name");
	String password=request.getParameter("password");
	String codekey=request.getParameter("codekey");
	String token=request.getParameter("token");
	String sessionCodekey=(String) request.getSession().getAttribute("randomString");//验证码
//获取session中的token值
	String sessiontoken=(String) request.getSession().getAttribute("token");
	if (token!=null && token.equals(sessiontoken)) {
//判断Form表单的token和session中的token是否相等
	request.getSession().removeAttribute("token");
	if (codekey!=null && codekey.equalsIgnoreCase(sessionCodekey)) {
	IUserService userService=new UserSerivceImpl();
	UserPo dbUser=userService.login(name);
	if (dbUser!=null) {					
	if (dbUser.getPassword().equals(password)) {
		request.getSession().setAttribute("gUser", dbUser);	
		} else {
		request.setAttribute("error", "密码错误");
		request.getRequestDispatcher("/jsp/error.jsp").forward(request, response);
	}
} else {
		request.setAttribute("error", "没有此用户");
		request.getRequestDispatcher("/jsp/error.jsp").forward(request, response);
	}			
} else {
		response.sendRedirect("../index.jsp");//重定向页面
			}
		} else {
			System.out.println("重复提交");
			response.sendRedirect("../index.jsp");
		}
	}

输出结果图:

在这里插入图片描述

发布了37 篇原创文章 · 获赞 8 · 访问量 5946

猜你喜欢

转载自blog.csdn.net/weixin_43741599/article/details/94992251