实战演练如何防止重复提交

介绍

对于表单重复提交对于大家来说都不陌生,就是说当我们在进行表单提交时候,有可能出现网络延迟的情况,这个时候我们又点击按钮进行了表单的重复提交,对于以下的情况,我们可能就只是进行了两次的登录,对于这种情况问题还不是很大。
在这里插入图片描述
但是对于以下的情况,当我们在进行第一次转账时候,输入了密码,却发现并没有得到任何的响应,于是又进行了一次的转账,这个时候就可能会导致两次的转账的出现,这种情况来说是比较严重的。
在这里插入图片描述

对于重复提交我们也有一些的解决方案----前端验证:

  1. 就是在ajax提交之后把按钮给禁用掉,就是在没有得到响应之前,是不能够重复点击按钮的。
  2. 若是使用form表单进行提交,对于js提交表单之前将按钮禁用掉 。使用到的是disabled 属性。也能够防止表单的重复提交。

注意:但是以上的情况对于重复刷新页面,或者是使用url直接提交请求信息还是会出现问题。所以这里我们介绍一下对于使用token字符串进行验证提交。

token字符串

对于以下时序图我们进行讲解:

  1. 在页面提交请求之前,会先提交一个ajax请求(这个请求可以是我们自己定义,定义为在点击提交按钮之前就先进行一次提交请求,并将信息返回回来。),让后台系统生成一个UUID字符串作为令牌,同时保存到HttpSession中,最终这个HttpSession会返回给前端的页面。
  2. 在页面正式开始请求时候,不仅会带上必须要传递的信息,同时还会带上这个UUID字符串,后台会将HttpSession中保存的字符串与这一次请求时候上传的字符串进行一个比对,若是相等,表示是同一次的请求,就继续执行,同时会把HttpSession里面的令牌删除。然后执行正常的方法。
  3. 那么对于这种方法是如何防止表单的重复提交呢? 思考一下 对于我们在第一次提交的过程中,对于请求还没到达后台,此时用户又重复进行了页面的刷新,此时这次的请求正常请求到了后台并进行了响应,但是此时第一次请求到了,但是对于第一次请求的字符串和第二次正常请求的字符串并不相等,所以说服务器也并不会对携带这个字符串的请求进行响应,所以也就可以保证表单的重复提交。
    在这里插入图片描述

编程实现

  1. 我们先创建一个用来生成token字符串的类来模拟在正式请求之前的token字符串的生成和删除。
@RestController
@RequestMapping("/token")
public class tokenController {

    @RequestMapping("/save")
    public R save(HttpServletRequest request){
        HttpSession session=request.getSession();
        String token= UUID.randomUUID().toString();
        session.setAttribute("token",token);
        return R.ok().put("token",token);
    }
    //R 是本项目自己封装的一个类 不用在意。
    @RequestMapping("/remove")
    public R remove(HttpServletRequest request){
        HttpSession session=request.getSession();
        session.removeAttribute("token");
        return  R.ok();
    }
}

首先我们使用到postman来进行正式提交之前的提交获取token字符串的提交,可以看到的是,返回给我们正确的信息,这个token字符串我们会在下一次请求时候带上,同时也存在与Httpsession中。
在这里插入图片描述

  1. 下面来模拟测试一下:测试代码如下
  • 首先判断给定的session中是否存在token 存在进行取出来,然后和上传的进行比对,若是不想等,表示不是同一次请求。
  • 若是同一次请求,将token信息删除,返回正确的信息。
  • 我们在测试时候发现,对于第一次的请求可以返回正确的信息,对于重复提交,因为token已经被删除,认定为第二次的提交,不进行处理。
@RestController
@RequestMapping("/test")
public class textController {

    @RequestMapping("demo1")
    public R save(HttpServletRequest request,
                  @RequestParam Map<String,Object>  map){

        HttpSession session=request.getSession();
        String token="";
        if(session.getAttribute("token")!=null){
            token=session.getAttribute("token").toString();
        }
        if(!token.equals(map.get("token").toString())){
            return  R.error("token error");
        }
        session.removeAttribute("token");
        // 写上自己的业务代码。
        return  R.ok();
        
    }
}

点击第一次发起请求,因为我们的Httpsession中保存了对应的session,此时我们又进行一个上传,可以看到返回的是正确信息。
在这里插入图片描述
然后我们相同url点击第二次请求,发现请求出现错误
在这里插入图片描述

后记

对于我们第一次提交时候可能会出现网络延迟,用户刷新页面,重复提交,这个时候这个提交到达服务器,生成一个token信息保存在HttpSession中,然后用户正式提交表单等,发现此时提交带的token信息(是我们一次提交两次请求的第一次请求返回的token)和HttpSession中token信息相同(因为同时也保存在了Httpsession中),表示是同一次提交,后台进行处理,然后将token删除。当第一次提交到达服务端以后,发现的是此时的token信息和HttpSession信息不想等,或者说HttpSession中已经不存在token,就绝对不会将此次的提交给上传上去,就可以防止重复提交。以上就是模拟使用token来防止重复提交,这里也只是提供一个小小的思想,有什么错误的地方还望大家能够指证出来。

发布了104 篇原创文章 · 获赞 92 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44015043/article/details/105741451
今日推荐