session 的运用——防止表单重复提交——1.0版
session 的应用——防止表单重复提交——1.0版
1). 表单的重复提交:
> 在表单页面, 多次点击 "提交" 按钮.
> 在转发的情况下, "刷新" 在成功页面
> 点击 "后退" 后, 再次提交表单.
2). 不属于表单重复提交:
> 点击 "后退" 后,刷新表单页面 , 再次提交表单. 属于是一个新的请求
3). 思路:
> 在表单中做一个标记
> 在 Servlet 中验证标记是否存在, 若存在, 受理请求, 同时销毁标记; 若不存在, 视为重复提交
4). 步骤:
> 做标记
* 在表单中使用隐藏域: 不行! 因为在点击 "刷新" 时, 隐藏域和一般的表单域是一样的, 都会被提交到 Servlet 中.
* 放在 request 属性中: 不行! 因为 form 页面的 request 和点击 "提交" 按钮的 request 是两个不同的请求.
* 放在 session 属性中:
> 在 Servlet 中进行验证:
* 获取标记
* 检查标记是否为空, 若为空, 则按重复提交处理; 若不为空, 将其从 session 中清除, 处理表单
5). 完善:
> 在 Session 中放入的值应该是一个随机值, 且唯一: 使用当前的系统时间
> 在 Servelt 中不但要检验 Session 的值是否存在, 还要检查 Session 中的值是否和当时放的值是否一致: 把 Session 中的属性值放在隐藏域中
代码实现:
xml 文档自己配
1). 表单的重复提交:
> 在表单页面, 多次点击 "提交" 按钮.
> 在转发的情况下, "刷新" 在成功页面
> 点击 "后退" 后, 再次提交表单.
2). 不属于表单重复提交:
> 点击 "后退" 后,刷新表单页面 , 再次提交表单. 属于是一个新的请求
3). 思路:
> 在表单中做一个标记
> 在 Servlet 中验证标记是否存在, 若存在, 受理请求, 同时销毁标记; 若不存在, 视为重复提交
4). 步骤:
> 做标记
* 在表单中使用隐藏域: 不行! 因为在点击 "刷新" 时, 隐藏域和一般的表单域是一样的, 都会被提交到 Servlet 中.
* 放在 request 属性中: 不行! 因为 form 页面的 request 和点击 "提交" 按钮的 request 是两个不同的请求.
* 放在 session 属性中:
> 在 Servlet 中进行验证:
* 获取标记
* 检查标记是否为空, 若为空, 则按重复提交处理; 若不为空, 将其从 session 中清除, 处理表单
5). 完善:
> 在 Session 中放入的值应该是一个随机值, 且唯一: 使用当前的系统时间
> 在 Servelt 中不但要检验 Session 的值是否存在, 还要检查 Session 中的值是否和当时放的值是否一致: 把 Session 中的属性值放在隐藏域中
代码实现:
xml 文档自己配
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <% //取得唯一值 String time = "" +session.getId() + System.currentTimeMillis() ; session.setAttribute("token", time) ; %> <form action="LoginServlet" method="post"> <!-- 用隐藏域将表单做上标记 --> <input type="hidden" name="token" value="<%=time %>"/> <table border="1"> <tr> <td>Name:</td> <td> <input type="text" name="name"/> </td> </tr> <tr> <td>Password:</td> <td> <input type="password" name="password"/> </td> </tr> <tr rowspan="2"> <td> <input type="submit" value="Submit"/> </td> <td> <input type="reset" value="Reset"/> </td> </tr> </table> </form> </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> 注册成功! </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h4>表单已经提交!请不要多次提交!</h4> </body> </html>
package com.syh.servlet; import java.io.IOException; 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 LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response) ; } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { //模拟网速 Thread.sleep(3000) ; } catch (InterruptedException e) { e.printStackTrace(); } //0. 获取 "标记" boolean flag = true ; //1. 获取 HttpSession, 若 Session 不存在, 为重复提交 HttpSession session = request.getSession(false) ; if(null == session) { flag = false ; }else { //2. 从 Session 中获取指定的属性值, 若指定的值不存在, 也是为重复提交 String token = (String)session.getAttribute("token") ; if(null == token) { flag = false ; }else { //3. 从隐藏域中获取 Session 中存放的属性值, 若指定的值不存在, 也是为重复提交 String token2 = request.getParameter("token") ; if(null == token2) { flag = false ; }else { //4. 比较 token 和 token2 的值是否一致 if(token.equals(token2)) { //5. 从 Session 中移除属性 session.removeAttribute("token") ; } } } } if(!flag){ System.out.println("重复提交"); response.sendRedirect(request.getContextPath() + "/error.jsp") ; return ; } String name = request.getParameter("name") ; System.out.println("添加成功-->" + name); //这里必须用转发!仔细想想就明白了!因为转发的时候,URL 没有改变!当我们再次刷新的时候, //再次对该页面请求了!故而同一个表单再次请求了! request.getRequestDispatcher("/success.jsp").forward(request, response) ; //response.sendRedirect(request.getContextPath() + "/success.jsp") ; } }