session案例-防止表单重复提交
l 不足:但用户单击”刷新”,或单击”后退”再次提交表单,将导致表单重复提交
l 表单页面由servlet程序生成,servlet为每次产生的表单页面分配一个唯一的随机标识号,并在FORM表单的一个隐藏字段中设置这个标识号,同时在当前用户的Session域中保存这个标识号。
l 当用户提交FORM表单时,负责处理表单提交的serlvet得到表单提交的标识号,并与session中存储的标识号比较,如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。
l 在下列情况下,服务器程序将拒绝用户提交的表单请求:
l 存储Session域中的表单标识号与表单提交的标识号不同
l 当前用户的Session中不存在表单标识号
l 用户提交的表单数据中没有标识号字段
l 编写工具类生成表单标识号:TokenProcessor
l 一次性验证码的主要目的就是为了限制人们利用工具软件来暴力猜测密码。
l 服务器程序接收到表单数据后,首先判断用户是否填写了正确的验证码,只有该验证码与服务器端保存的验证码匹配时,服务器程序才开始正常的表单处理流程。
l 密码猜测工具要逐一尝试每个密码的前题条件是先输入正确的验证码,而验证码是一次性有效的,这样基本上就阻断了密码猜测工具的自动地处理过程。
代码如下:
TokenProcessor.java
package com.hbsi.servlet; import java.security.MessageDigest; importjava.security.NoSuchAlgorithmException; import java.util.Random; import sun.misc.BASE64Encoder; public class TokenProcessor { /*1.把构造方法私有化 * 2.创建一个实例对象 * 3.提供一个方法,让别人能获取到上面创建的实例对象 * * */ privateTokenProcessor(){ } privatestatic final TokenProcessor instance = new TokenProcessor(); publicstatic TokenProcessor getInstance(){ returninstance; } publicString generateToken(){ inti = new Random().nextInt(); Stringtoken = System.currentTimeMillis()+ i+""; try{ MessageDigestmd =MessageDigest.getInstance("md5"); byte[]md5 = md.digest(token.getBytes()); //base64编码 BASE64Encoder encoder = new BASE64Encoder(); returnencoder.encode(md5); //returnnew String(md5); }catch (NoSuchAlgorithmException e) { thrownew RuntimeException(e); } } }
FormGenerateServlet.java
package com.hbsi.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; public class FormGenerateServlet extendsHttpServlet { publicvoid doGet(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriterout = response.getWriter(); //产生表单号 TokenProcessortp = TokenProcessor.getInstance(); Stringtoken = tp.generateToken(); request.getSession().setAttribute("token",token); out.print("<formaction='/BookHistory/servlet/FormDealServlet' method='post'>"); out.print("<inputtype='hidden' name='token' value='"+token+"'/>"); out.print("用户名:<input type='text'name='username' />"); out.print("<inputtype='submit' value='提交'/>"); out.print("</form>"); } publicvoid doPost(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException { doGet(request,response); } }
FormDealServlet.java
package com.hbsi.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; public class FormDealServlet extendsHttpServlet { publicvoid doGet(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException { booleanb = isTokenValidate(request); if(!b){ System.out.println("请不要重复提交表单"); return; } request.getSession().removeAttribute("token"); System.out.println("向数据库注册用户信息。。。"); } privateboolean isTokenValidate(HttpServletRequest request){ Stringclient_token = request.getParameter("token"); if(client_token==null){ returnfalse; } Stringserver_token = (String) request.getSession().getAttribute("token"); if(server_token==null){ returnfalse; } if(!client_token.equals(server_token)){ returnfalse; } returntrue; } publicvoid doPost(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException { doGet(request,response); } }