在注册用户或者其他的时候 必须要防止恶意的表单重复提交, 其中可是使用javascript代码在点击提交按钮之后将按钮变灰 防止 重复提交 但是 这只可以防止平常的用户表单提交,对于懂技术的恶意用户,使用JavaScript无法防止恶意提交 ,这时候 便需要在服务器中防止 。
防止的具体方法思路是:
创建一个令牌,当用户运行提交表单的servlet时,利用令牌随机创建一个字符串, 并将其放在隐藏表单中(hidden属性) 然后将这个令牌也放在session中 用户提交表单跳转到下一个页面,在这个页面中 判断令牌是否 有效,就是判断session中的令牌和 表单中的令牌是否一致,若不一致则无效。 在提交成功后应该将session中的令牌删除,在下次重复提交时就可以判断不一致,阻止提交!!!
其中包括2个servlet和一个jsp
第一个servlet是 用来创建session和 产生随机数的 将随机数放入表单中 这样可以防止恶意用户自己写一个表单提交 因为我们的表单有令牌 他的没有 然后第一个servlet跳转到jsp页面
在jsp页面课直接获取token令牌值 使用 ${token}即可 其中令牌值 用hidden 属性隐藏
点击提交后 在第二个servlet处理结果
所以 第二个servlet来判断是否重复提交 方法就是对比session中和表单中的令牌是否一致 如果一致 成功 并且删除session 即可
具体代码如下:
servlet1:
package cn.sessions; import java.io.IOException; import java.io.PrintWriter; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Random; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import sun.misc.BASE64Encoder; public class FormServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String token = TokenProcess.getInstance().generateToken(); request.getSession().setAttribute("token", token); request.getRequestDispatcher("/form.jsp").forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } class TokenProcess{ //将构造函数设为私有 即外界不可创建对象,可保证对象的唯一性 private TokenProcess(){} private static final TokenProcess instance = new TokenProcess(); //像外界提供一个获取该唯一对象的接口 public static TokenProcess getInstance(){ return instance; } public String generateToken(){ //通过当前时间毫秒值和随机函数 获取一个随机数 String token = System.currentTimeMillis()+new Random().nextInt()+""; //由于上述获取的随机数长度不定 所以要采用数据摘要类获取固定长度的随机数 MessageDigest try { MessageDigest md = MessageDigest.getInstance("md5"); byte[] md5 = md.digest(token.getBytes()); //又由于md5数组如果转换为字符串基本上会是乱码 所以要用Base64Encoder 来进行转换 成字符串 BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(md5); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(); } } }
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'form.jsp' starting page</title> </head> <body> <form action="/cooks/servlet/DoFormServlet"> <input type="hidden" name="token" value="${token}"> 用户名: <input type="text" name="username"> <br/> <input type="submit" value="提交"> </form> </body> </html>
package cn.sessions; 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; import javax.servlet.http.HttpSession; public class DoFormServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); boolean b = isTokenRiget(request); if(!b){ System.out.println("请不要重复提交"); return; } request.getSession().removeAttribute("token"); System.out.println("写入数据库"); } /** * 此函数的作用是用来判断token是否有效的 * */ private boolean isTokenRiget(HttpServletRequest request) { String token = request.getParameter("token"); HttpSession session = request.getSession(); String tokenSession = (String) session.getAttribute("token"); if(token==null){ return false; } if(tokenSession==null) return false; if(!tokenSession.equals(token)){ return false; } return true; } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }