java http重复提交_Java Web之表单重复提交问题

上篇文章讲了验证码的制作,提及到了一个问题,就是表单重复提交的问题,可能在上次那个验证码中感觉不是那么的重要

现在我新写一个例子,转钱。通过这个例子你就知道表单重复提交有多恐怖了。

先来简单的介绍一下表单重复提交的3种现象

4cdac11d5bcd25e4a24e0dffa945263a.png

我们来一个个的实验,首先我们写两个东东,一个jsp,一个Servlet,jsp写了就不动了,Servlet会变化,我会在不同的现象下贴出代码

JSP:

转账

转账金额: 元

Servlet我们会在不同的现象修改,下面直接看

1.服务器慢或者网络延迟,我们使用线程模拟一下

先看Servlet

packagecom.vae.RandomCode;importjavax.servlet.ServletException;importjavax.servlet.annotation.WebServlet;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.IOException;importjava.io.PrintWriter;

@WebServlet("/transform")public class TransformServlet extendsHttpServlet {

@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throwsServletException, IOException {

resp.setContentType("text/html;charset=utf-8");

PrintWriter out=resp.getWriter();

String money=req.getParameter("money");try{

Thread.sleep(1000);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println("转出:" +money);

out.println("转账成功");

}

}

运行,如图:

80863b7200f12ad8b4b44b7462d70003.png

我点击注册,其实是转账。。。。

然后应该出现一大串的转账100,但是不知道怎么回事,我用线程模拟的情况并没有出现转账多次,所以这里暂时疑惑

2.已经提交成功,不小心刷新了页面

(Servlet代码删了线程就行了)

6bcc47d76dd2ae42bb94f7722119f375.png

我们点击一次

91d1e44a40cf1936bec6078ee4a6f221.png

然后我不小心的刷新了几次页面

18dca53c33833c8b321e5b1b5e7e819a.png

卧槽???啥情况?我就是不小心刷新了几次,就要我多转出去钱???明显不合理

3.已经提交成功了,我回退,再次点击提交,我就是这么的事多.....

9c814eb1d17043ffd5d2b00fea375ead.png

我点

9cfc734b60e0dc2e649cd84ec4dc6f0e.png

我回退

808e6fdd7584c238564ec209e77b1c85.png

我再点

e22489c175a1d29ea318dfe023b82b8e.png

。。。。。这种情况也是不行的。。。。虽然是用户自己作死。。。。。但是还是要规避一下。。。。

通过上面3个例子,我们知道了表单重复提交的恐怖,特别是涉及到钱的方面。所以我们要想个办法来规避这种情况,怎么办呢?

想想,我们是不是通过两次请求就可以实现转账了,一次是JSP的按钮点击,一次是Servlet的获取数据,那么我们只需要保证我们每次的操作,都有这两次请求就可以了

解决方案:令牌机制

我听到这个令牌机制就想起了狄仁杰...其实令牌机制就是一个随机数UUID,和我们的验证码里面的那个是一样的。其原理是

我在JSP页面点击按钮发出第一次请求的时候,就把我的令牌(随机数)保存到Session里面,并且把令牌传给Servlet,然后在Servlet里面判断两个是否相等

如果相等,就ok,转账,然后立马销毁session里面的令牌,这样无论你再怎么刷新,session里面已经没有令牌了,肯定不能转账了

话说到此,我们来看看最终的代码

JSP:

转账

//生成一个令牌Stringtoken=UUID.randomUUID().toString();//存放在session中

session.setAttribute("TOKEN_IN_SESSION",token);%>

"> 转账金额: 元

Servlet:

packagecom.vae.RandomCode;importjavax.servlet.ServletException;importjavax.servlet.annotation.WebServlet;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.IOException;importjava.io.PrintWriter;

@WebServlet("/transform")public class TransformServlet extendsHttpServlet {

@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throwsServletException, IOException {//表单中的令牌

String tokenInRequest=req.getParameter("token");//session中的令牌

String tokenInSession=req.getSession().getAttribute("TOKEN_IN_SESSION").toString();//比较

if(tokenInRequest.equals(tokenInSession)) {//立马销毁session中的令牌再说

req.getSession().removeAttribute("TOKEN_IN_SESSION");//然后干其他的事

resp.setContentType("text/html;charset=utf-8");

PrintWriter out=resp.getWriter();

String money=req.getParameter("money");

System.out.println("转出:" +money);

out.println("转账成功");

}else{

System.out.println("不让你转,重新去页面转吧");

}

}

}

运行一下,结果已经ok了,我们使用了令牌机制(就是一个随机数)实现了避免表单的重复提交。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值