表单重复提交与验证码
前言
了解表单重复提交的几种可能,以及使用验证码标识请求的唯一性来解决此问题。
一、表单重复提交
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>验证码: </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尚硅谷