[Jsp]防止页面表单重复提交的解决方法
个人学习笔记,写下方便以后复用。
当我们写了个注册页面时候,用户完成注册并提交,用户注册的资料并录入数据库保存,最不希望出现的是在一个会话中出现多次提交的结果,我们可以通过为请求设置标记来避免此类事件的发生。
1.为每个请求设置一个标记,当此页面是首次被请求时,生成标记并放入session中,并且把此生成的标记的值作为隐含标签传递到处理页面
2.提交表单时,跳转页面处理请求中的标记,如果判断请求中session对象的标记和隐含标签中的值相同,处理请求,并将session中的标记值去除
( TokenGen.java)
package com.beans; import java.util.*; import javax.servlet.http.*; public class TokenGen { private static TokenGen instance = new TokenGen(); private TokenGen() {} public static TokenGen getInstance() { return instance; } public synchronized boolean isTokenValid(HttpServletRequest request) { // 没有session,判为非法 HttpSession session = request.getSession(false); if (session == null) return false; // session中不含token, // 说明form被提交过后执行了resetToken()清除了token // 判为非法 String stoken = (String) session.getAttribute("token"); if (stoken == null) return false; // request请求参数中不含token, // 判为非法 String rtoken = request.getParameter("token"); if (rtoken == null) return false; // request请求中的token与session中保存的token不等,判为非法 return stoken.equals(rtoken); } /* * 重新设置token,当页面被请求后,将session中的token属性去除 */ public synchronized void resetToken(HttpServletRequest request) { HttpSession session = request.getSession(false); if (session!=null) { session.removeAttribute("token"); } } /* * 为请求新建一个token标记,此标记由一个随机的double数toString形成,并把字符值存入session中 */ public synchronized void saveToken(HttpServletRequest request) { HttpSession session = request.getSession(true); Random rand = new Random(); Double d = rand.nextDouble(); session.setAttribute("token", d.toString()); } }
(form.jsp) 其中加粗加红为生成token标记的代码
<%@ page language="java" import="com.beans.*" pageEncoding="gb2312"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>注册页面1</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> </head> <% TokenGen.getInstance().saveToken(request); String s = (String)session.getAttribute("token"); %> <body> <form id="form1" name="form1" method="post" action="register.jsp"> <table align="center"> <tr> <td colspan="2"><br><input type="hidden" name="token" value="<%=s%>"/> </td> </tr> <tr> <td align="right"> 用户名: </td> <td> <input type="text" name="t1" /> </td> </tr> <tr> <td align="right"> 密码: </td> <td> <input type="password" name="t2" /> </td> </tr> <tr> <td align="right"> 确认密码: </td> <td> <input type="password" name="t3" /> </td> </tr> <tr> <td align="right"> 性别: </td> <td> <input type="radio" name="radio" id="radio" value="boy" /> 男 <input type="radio" name="radio" id="radio2" value="gril" /> 女 </td> </tr> <tr> <td align="right"> 个人说明: </td> <td> <textarea name="textraea1" rows="15" cols="60"></textarea> </td> </tr> <tr> <td align="right"> <input type="submit" name="button" id="button" value="提交" /> </td> <td> <input type="reset" name="button2" id="button2" value="重置" /> </td> </tr> </table> </form> </body> </html>
<%@ page language="java" import="com.beans.*" pageEncoding="gb2312"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>处理注册页面1</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <% TokenGen tokenGen=TokenGen.getInstance(); if (!tokenGen.isTokenValid(request)) { out.print("这是重复提交或非法提交!"); } else { // 处理请求,并执行resetToken方法,将session中的token去除 tokenGen.resetToken(request); } %> </body> </html>