表单重复提交与验证码

表单重复提交与验证码

前言

了解表单重复提交的几种可能,以及使用验证码标识请求的唯一性来解决此问题。

一、表单重复提交

1、常见场景

A.请求转发

1)问题描述
当处理完一个业务之后,通过请求转发去处理另一个业务,如果此时刷新就会重复上面的整个请求过程。如添加一个图书信息之后,请求转发到图书信息展示页面,如果此时刷新页面,则会再次添加图书,然后再到图书展示页面。
2)解决方案
通过将两次业务重一次请求中分割成两个请求,可以使用重定向。

B.网络延迟

问题描述)
当处理完一个业务之后,由于网络原因,response还未将数据送到浏览器,此时用户重复发起请求导致表单重复提交。如用户注册用户信息时,填好用户信息之后,点击注册,但是由于网络原因导致页面未刷新,用户着急则重复点击注册,导致表单多次提交。
解决方案)
验证码唯一标识一次请求。

C.回退刷新

问题描述)
当浏览器提交表单,页面刷新之后,用户故意回退到上一个页面再次进行提交,导致表单重复提交。如用户注册之后,又回退到前一个注册页面点击注册按钮,导致重复注册。
解决方案)
验证码唯一标识一次请求。

二、验证码

1、验证码解决原理

表单重复提交与验证码

2、Google验证码使用

A.Step

1)导入kaptcha.jar包
2)web.xml配置其写好的KaptchaServlet类

<!-- 配置验证码第三方包-->
    <servlet>
        <servlet-name>KaptchaServlet</servlet-name>
        <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>KaptchaServlet</servlet-name>
        <url-pattern>/kaptcha.jpg</url-pattern>
    </servlet-mapping>

3)在表单中使用img标签请求获取验证码

B.Code

<label>验证码:&nbsp;&nbsp;&nbsp;</label>                                      
<input class="itxt" type="text" style="width: 150px;" id="code" name="code"
       value="${requestScope.code}"/>                                      
<img alt="" src="kaptcha.jpg" id="yzm"                                     
     style="float: right; margin-right: 10px;width: 100px;height: 40px">   
<script type="text/javascript">                                            
    $(function () {                                                        
        $("#yzm").click(function () {                                      
            //这里必须使用this,而不是$("#yzm")                                      
            this.src = "kaptcha.jpg?d=" + new Date()//防止请求一致,浏览器使用缓存的数据    
        })                                                                 
    })                                                                     
</script>                                                                  
<br/>                                                                      
<br/>                                                                      
private UserService us = new UserServiceImpl();

    /**
     * @param req
     * @param resp
     * @function 注册方法
     */
    protected void register(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        //1.将参数注入到Bean对象中
        User user = ParamToBean.paramToBean(req.getParameterMap(), new User());
        String code = req.getParameter("code");
        String yzm = String.valueOf(req.getSession().getAttribute(KAPTCHA_SESSION_KEY));
        //2.判断验证码是否错误获取该用户名是否被注册
        if (!yzm.equalsIgnoreCase(code)) {
            req.setAttribute("errorMsg", "验证码不正确");
            req.setAttribute("user", user);
            req.setAttribute("code", code);
            req.getRequestDispatcher("/pages/user/register.jsp").forward(req, resp);
            return;
        }
        //一旦验证码正确就必须将其置为null,防止表单重复提交过来
        req.getSession().removeAttribute(KAPTCHA_SESSION_KEY);
        //另一种失败情况
        if (us.isExistUserByName(user.getUsername()) || !us.isRegister(user)) {
            //System.out.println("应该回到注册页面");
            req.setAttribute("errorMsg", "验证码不正确或该用户名已存在");
            req.setAttribute("user", user);
            req.setAttribute("code", code);
            req.getRequestDispatcher("/pages/user/register.jsp").forward(req, resp);
            return;
        }
        //3.注册成功
        req.getRequestDispatcher("/pages/user/register_success.jsp").forward(req, resp);
    }

总结

1)表单重复提交的几种方式
2)验证码的使用

参考文献

[1] Java Web尚硅谷

上一篇:node.js+MySQL知识点


下一篇:【C#】.Net 腾讯云一句话识别 【实例】