`

session 的应用——防止表单重复提交——1.0版

阅读更多

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") ;
		
		 
	

	}	
}
 
分享到:
评论

相关推荐

    php表单加入Token防止重复提交的方法分析

    Token一般用在两个地方——防止表单重复提交、anti csrf攻击(跨站点请求伪造)。 两者在原理上都是通过session token来实现的。当客户端请求页面时,服务器会生成一个随机数Token,并且将Token放置到session当中,...

    getAttribute和getParameter区别.

    ——getParameter:用于客户端重定向时,即点击了链接或提交按扭时传值用,即用于在用表单或url重定向传值时接收数据用。 ——getAttribute:用于服务器端重定向时,即在sevlet中使用了forward函数,或struts中使用了...

    JSP由浅入深(12)—— 表单编辑

    从下面的例子的例子中我们可以学到怎样修改GetName.jsp以提供类似于blx:getProperty的特性,但是我们只能手工地编辑HTML标志:&lt;jsp id=user class=UserData scope=session/&gt;&lt;HTML&gt;&lt;BODY&gt;&lt;FORM METHOD...

    JAVA WEB典型模块与项目实战大全

    5.5 避免重复提交功能  5.6 缩略加水印图像  5.7 小结  第6章 网络硬盘  6.1 网络硬盘功能原理  6.2 网络硬盘功能具体实现——浏览磁盘和显示文件信息  6.3 网络硬盘功能具体实现——操作文件夹和文件...

    Python使用requests提交HTTP表单的方法

    ...以http post,即浏览器提交一个表格数据到web服务器,为例,来说明requests的使用。 无cookie import requests ...data = {'username': 'user', 'password': '123456'} ...有cookie——显示添加cookie import reques

    Java Web编程宝典-十年典藏版.pdf.part2(共2个)

    3.10.1 表单提交中文数据乱码 3.10.2 如何在超链接中传递多个参数 3.10.3 重定向后出现404错误 3.11 精彩回顾 第4章 体验面向对象 1IavaBean技术 4.1 本章学习任务 4.1.1 本章知识体系 4.1.2 实例开发任务 4.2 ...

    php网络开发完全手册

    12.6 JavaScript和PHP的综合实例——表单 12.6 验证 197 12.6.1 表单设计 197 12.6.2 JavaScript代码设计 199 12.6.3 PHP代码设计 200 12.6.4 代码的运行 201 12.7 小结 202 第2篇 PHP与数据库 第13章 关系型数据库...

    PHP开发实战1200例源码

    实例172 不提交表单获取单选按钮的值 207 实例173 实现复选框中的全选、反选和不选 208 实例174 隐藏域提交用户的ID值 210 实例175 图像域替代提交按钮 211 实例176 跳转菜单实现页面跳转 213 实例177 上传图片预览 ...

    JSP网站开发典型模块与实例精讲

     1.4.5 指点迷津——连接数据库常见问题  1.5 调试和错误处理  1.5.1 使用MyEclipse实现快速调试  1.5.2 使用System.out监控变量  1.5.3 为JSP指定一个错误处理页面  1.6 独家见解——B/S结构与C/S结构...

    asp.net知识库

    SubmitOncePage:解决刷新页面造成的数据重复提交问题 SharpRewriter:javascript + xml技术利用#实现url重定向 采用XHTML和CSS设计可重用可换肤的WEB站点 asp.net的网址重定向方法的比较:面向搜索引擎友好 也谈 ...

    Java Web程序设计教程

    2.4项目实战——第一个javaee应用:helloworld 28 2.4.1开始创建第一个javaee应用 28 2.4.2熟悉helloworld框架结构 29 本章小结 32 课后练习 32 第3章jsp和servlet 33 3.1开发第一个jsp+servlet应用 33 3.1.1...

    Spring shiro + bootstrap + jquery.validate 实现登录、注册功能

    现在我们开始实现登录功能,这个可以说是Web应用最最最普遍的功能了。 先来说说我们登录的逻辑: 输入用户名、密码(validate进行前端验证)——ajax调用后台action方法——根据用户名调用业务层到数据层查询数据库...

    Web开发敏捷之道-应用Rails进行敏捷Web开发-第三版.rar

    22.3 Flash——Action之间的通信 364 22.4 过滤器与校验 366 22.5 缓存初接触 372 22.6 GET请求的问题 378 第23章 Action View 381 23.1 模板 381 23.2 使用辅助方法 385 23.3 用于格式化、链接和分页的辅助方法 386...

    PHP开发实战1200例(第1卷).(清华出版.潘凯华.刘中华).part1

    实例172 不提交表单获取单选按钮的值 207 实例173 实现复选框中的全选、反选和不选 208 实例174 隐藏域提交用户的ID值 210 实例175 图像域替代提交按钮 211 实例176 跳转菜单实现页面跳转 213 实例177 上传图片预览 ...

    PHP开发实战1200例(第1卷).(清华出版.潘凯华.刘中华).part2

    实例172 不提交表单获取单选按钮的值 207 实例173 实现复选框中的全选、反选和不选 208 实例174 隐藏域提交用户的ID值 210 实例175 图像域替代提交按钮 211 实例176 跳转菜单实现页面跳转 213 实例177 上传图片预览 ...

    低清版 大型门户网站是这样炼成的.pdf

    低清版51M 大型门户网站是这样炼成的!(Struts 2+Spring 2+Hibernate 3).pdf(完整版) 网上有高清版350M的。可以去下 http://115.com/file/be5gwid8 请于下载后 24H 内及时删除!请抱着学习的态度下载此资料。 ...

    learning_way:一套通用的学习WEB端语言的方法和路径

    WEB语言学习路径 0.开发环境服务安装以及开发工具的安装使用,在页面上输出Hello World ... 推荐链接: ...表单提交获取(post,get,del,put,patch) 文件操作以及上传保存 JSON/XML操作 Cookie操作 Session操

    外文翻译 stus MVC

    Struts——an open-source MVC implementation This article introduces Struts, a Model-View-Controller implementation that uses servlets and JavaServer Pages (JSP) technology. Struts can help you control...

    深入浅出Struts 2 .pdf(原书扫描版) part 1

    第15章 防止重复提交 252 15.1 标记管理 252 15.2 使用Token拦截器 253 15.3 使用Token Session拦截器 256 15.4 小结 257 第16章 调试与性能分析 258 16.1 debug标签 258 16.2 Debugging拦截器 259 16.3 性能分析 ...

Global site tag (gtag.js) - Google Analytics