session案例1:防止表单重复提交 原理: 1,表单页面由servlet程序生成,servlet为每次产生的表单页面分配一个唯一的随机标识号,并在FORM表单的一个隐藏字段中设置这个标识号,同时在当前用户的Session域中保存这个标识号。 2,当用户提交FORM表单时,负责处理表单提交的serlvet得到表单提交的标识号,并与session中存储的标识号比较,如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。 3,在下列情况下,服务器程序将拒绝用户提交的表单请求: 当前用户的Session中不存在表单标识号 用户提交的表单数据中没有标识号字段 存储Session域中的表单标识号与表单提交的标识号不同 设计: // 生成界面,生成一个随机的唯一的随机标识号(令牌token) RegistUIServlet 实现功能: 1,把token存放到HttpSession中 2,提供一个含有type=hidden的输入表单 // 处理数据 RegistServlet 实现功能: 1,获取表单提交上来的令牌token 2,获取HttpSession中存的令牌 通过比对表单提交上来的token的值和HttpSession中token的值来判断是否为重复提交: 若二者相等,则: 1,进行真正的数据处理(业务处理) 2,删除HttpSession中保存的token 若二者不相等时,则:说明是重复提交的表单 【注意】 1,刷新或重复提交时,只是提交了表单,并没有再往session中存token。即:刷新或重复提交仅仅是重新传递了token。 2,在第一次提交后,RegistServlet就把session中的token就被清除了。所以在重复提交时,session中并没有token,故二者肯定不相等了。 ----------------------------------------------------- // 处理注册的请求,同时判断是否是重复提交 public class RegistServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); request.setCharacterEncoding("UTF-8"); String name = request.getParameter("name"); try { Thread.sleep(2000);//模拟一下网络的延迟 } catch (InterruptedException e) { e.printStackTrace(); } //判断用户是否重复提交 String formToken = request.getParameter("token"); String sessionToken = (String) request.getSession().getAttribute("token"); if(formToken.equals(sessionToken)){ //正常提交 System.out.println("保存了:"+name); request.getSession().removeAttribute("token"); }else{ out.write("请不要重复提交"); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } --------------------- //生成注册页面 public class RegistUIServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); //生成一个随机的令牌 String token = ""+System.currentTimeMillis()+new Random().nextLong(); //算数据指纹,用MD5算法 token = MD5Util.md5(token); // 或者使用UUID生成一个随机的令牌 //String token = UUID.randomUUID().toString();//唯一的一段序列 //放入HttpSession中 request.getSession().setAttribute("token", token); out.write("<form id='f1' action='"+request.getContextPath()+"/servlet/RegistServlet' method='post'>"); out.write("姓名:<input type='text' name='name'/><br/>"); out.write("<input type='hidden' name='token' value='"+token+"'/>"); out.write("<input id='bt1' type='button' value='注册' onclick='toSubmit()'/></form>"); // 在客户端防止重复提交,但是不能防止刷新 out.write("<script type='text/javascript'>function toSubmit(){document.getElementById('f1').submit();document.getElementById('bt1').disabled=true;}</script>"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } session案例2:一次性校验码 目的:一次性验证码的主要目的就是为了限制人们利用工具软件来暴力猜测密码。 原理: 1,服务器程序接收到表单数据后,首先判断用户是否填写了正确的验证码,只有该验证码与服务器端保存的验证码匹配时,服务器程序才开始正常的表单处理流程。 2,密码猜测工具要逐一尝试每个密码的前题条件是先输入正确的验证码,而验证码是一次性有效的,这样基本上就阻断了密码猜测工具的自动地处理过程。
原文地址:http://blog.csdn.net/wodewutai17quiet/article/details/46239037