防止表单重复提交

在注册表单中,我们会遇到表单重复提交

在这里有两种解决方案,一种是在前端阻止,一种在服务器端阻止

1.在javaScript里阻止表单重复提交

<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
	//定义一个全局变量
	//这个变量用来记住表单是否提交过,提交过便置为true
	var iscommitted = false;
	function dosubmit(){
		//当表单为false时  便返回true  并将iscommitted改为true
		if(!iscommitted){
			iscommitted = true;
			return true;
		}
		return false;
	}
</script>
</head>
<body>
	<!-- 
		表单添加一个onsubmit事件 
		该事件调用的方法返回true时便提交表单
	-->
	<form action="/sd/dfs" method="post" οnsubmit="return dosubmit()">
		用户名:<input type="text" name="username" />
		<input type="submit" value="提交">
	</form>
</body>
</html>

在实际开发中javaScript的方法是有漏洞的(如果有人想重复提交还是有办法重复提交的)

所以我们还需要在服务器端一起阻止表单重复提交


2.在服务器端阻止表单重复提交

思路:表单由程序输出给浏览器,在每个表单里设置唯一的表单号,并且将表单号存储在服务器。提交表单后,服务器拿出表单号进行比较,如果有便表示没有提交过,然后删除表单号。

我们写一个servlet用于产生表单号

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//产生随机数(表单号)  我们需要创建一个随机数的发生器
		TokenProcessor instance = TokenProcessor.getInstance();
		String token = instance.generateToken();
		//将随机数存入session   方便到时候 验证
		HttpSession session = request.getSession();
		session.setAttribute("token", token);
		//请求转发
		request.getRequestDispatcher("/form.jsp").forward(request, response);
		
	}
创建一个随机数生产器

//创建一个随机数的发生器
class TokenProcessor{//token:令牌
	/*
	 * 单例设计模式
	 * 	1.把构造方法私有
	 * 	2.自己创建一个
	 * 	3.对外暴露一个方法,允许获取上面创建的对象
	 */
	private TokenProcessor(){}
	private static final TokenProcessor instance = new TokenProcessor();
	
	public static TokenProcessor getInstance(){
		return instance;
	}
	//产生随机数
	public String generateToken(){
		//获取当前时间  +  随机数
		String token =  System.currentTimeMillis()+ new Random().nextInt()+"";

	 try {
			//得到数据的摘要(指纹)  创建实例 "md5"算法
			MessageDigest md = MessageDigest.getInstance("md5");
			byte[] md5 = md.digest(token.getBytes());
			/* base64编码
			 * 然后数经过base64算法编码返回的都是一个明文字符串
			 * 会把三个字节变成四个字节   每三个字节变成四个字节
			 */
			BASE64Encoder encoder = new BASE64Encoder();
			return encoder.encode(md5);
		 } catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
	}
}
创建form表单

<%@ 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>
	<form action="/sd/dfs" method="post" >
		<input type="hidden" name="token" value="${token}">
		用户名:<input type="text" name="username" /><br/>
		<input type="submit" value="提交">
	</form>
</body>
</html>
我们访问该servlet

查看源码我们发现生成的随机数

当表单提交后,它会进入此servlet 进行表单号的判断来确定它是否是合理的请求

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//判断表单号是否有效
		boolean b = isTokenValid(request);
		if(!b){
			System.out.println("请不要重复提交");
			return;
		}
		request.getSession().removeAttribute("token");
		System.out.println("向数据库中注册用户");
	}
	//判断表单号是否有效
	private boolean isTokenValid(HttpServletRequest request) {
		//客户机带过来的表单号
		String client_token = request.getParameter("token");
		if(client_token==null){
			return false;
		}
		//获取session里的表单号
		String server_token = (String) request.getSession().getAttribute("token");
		if(server_token==null){
			return false;
		}
		//判断客户机的表单号与session里的表单号是否不相等
		if(!server_token.equals(client_token)){
			return false;
		}
		return true;
	}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值