表单重复提交之—–验证码
表单重复提交有三种常见的情况:
一:提交完表单。服务器使用请求转来进行页面跳转。这个时候,用户按下功能键 F5,就会发起最后一次的请求。造成表单重复提交问题。解决方法:使用重定向来进行跳转
二:用户正常提交服务器,但是由于网络延迟等原因,迟迟未收到服务器的响应,这个时候,用户以为提交失败,就会着急,然后多点了几次提交操作,也会造成表单重复提交。
三:用户正常提交服务器。服务器也没有延迟,但是提交完成后,用户回退浏览器。重新提交。也会造成表单重复提交。
谷歌 kaptcha 图片验证码的使用
谷歌验证码 kaptcha 使用步骤如下:
1、导入谷歌验证码的 jar 包
kaptcha-2.3.2.jar
2、在 web.xml 中去配置用于生成验证码的 Servlet 程序
<servlet>
<servlet-name>KaptchaServlet</servlet-name>
<servlet-class>top.qaqaq.servlet.MyKaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>KaptchaServlet</servlet-name>
<url-pattern>/kaptcha.jpg</url-pattern>
</servlet-mapping>
3、在表单中使用 img 标签去显示验证码图片并使用它
regist.jsp
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
<title>JSP - Hello World</title>
</head>
<body>
<form action="http://localhost:8080/JavaWeb_Code_Demo/registServlet" method="get">
用户名:<input type="text" name="username"> <br/>
验证码:<input type="text" style="width: 60px" name="code">
<img src="http://localhost:8080/JavaWeb_Code_Demo/kaptcha.jpg" alt="" style="width: 100px; height: 28px;"> <br/>
<input type="submit" value="注册">
</form>
<br/>
<a href="hello-servlet">Hello Servlet</a>
</body>
</html>
4、在服务器获取谷歌生成的验证码和客户端发送过来的验证码比较使用。
package top.qaqaq.servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import static com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY;
/**
* @author RichieZhang
* @create 2022-12-13 下午 2:26
*/
public class RegistServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doGet(req, resp);
// 获取Session中的验证码
String token = (String) req.getSession().getAttribute(KAPTCHA_SESSION_KEY);
// 删除 Session中的验证码
req.getSession().removeAttribute(KAPTCHA_SESSION_KEY);
// 获取表单项输入的验证码
String code = req.getParameter("code");
// 获取用户名
String username = req.getParameter("username");
if (token != null && token.equalsIgnoreCase(code)) {
System.out.println("保存到数据库:" + username);
//req.getRequestDispatcher("/ok.jsp").forward(req,resp);
// try {
// Thread.sleep(5000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
resp.sendRedirect(req.getContextPath() + "/ok.jsp");
} else {
System.out.println("请不要重复提交表单");
}
}
}
跳转网页ok.jsp
<%--
Created by IntelliJ IDEA.
User: ZRich
Date: 2022/12/13
Time: 下午 2:30
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
注册成功
</body>
</html>
切换验证码:
// 给验证码的图片,绑定单击事件
$("#code_img").click(function () {
// 在事件响应的function函数中有一个this对象。这个this对象,是当前正在响应事件的dom对象。
// src属性表示验证码img标签的 图片路径。它可读,可写
// alert(this.src);
this.src = "${basePath}kaptcha.jpg?d=" + new Date().getTime();
})
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0">
<servlet>
<servlet-name>RegistServlet</servlet-name>
<servlet-class>top.qaqaq.servlet.RegistServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RegistServlet</servlet-name>
<url-pattern>/registServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>KaptchaServlet</servlet-name>
<servlet-class>top.qaqaq.servlet.MyKaptchaServlet</servlet-class>
</servlet>a
<servlet-mapping>
<servlet-name>KaptchaServlet</servlet-name>
<url-pattern>/kaptcha.jpg</url-pattern>
</servlet-mapping>
</web-app>
注意:tomcat10使用kaptcha
package top.qaqaq.web;
import com.google.code.kaptcha.Producer;
import com.google.code.kaptcha.util.Config;
import jakarta.servlet.Servlet;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Properties;
/**
* @author RichieZhang
* @create 2022-12-13 下午 3:21
*/
public class MyKaptchaServlet extends HttpServlet implements Servlet {
private Properties props = new Properties();
private Producer kaptchaProducer = null;
private String sessionKeyValue = null;
private String sessionKeyDateValue = null;
public MyKaptchaServlet() {
}
public void init(ServletConfig conf) throws ServletException {
super.init(conf);
ImageIO.setUseCache(false);
Enumeration initParams = conf.getInitParameterNames();
while (initParams.hasMoreElements()) {
String key = (String) initParams.nextElement();
String value = conf.getInitParameter(key);
this.props.put(key, value);
}
Config config = new Config(this.props);
this.kaptchaProducer = config.getProducerImpl();
this.sessionKeyValue = config.getSessionKey();
this.sessionKeyDateValue = config.getSessionDate();
}
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setDateHeader("Expires", 0L);
resp.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
resp.addHeader("Cache-Control", "post-check=0, pre-check=0");
resp.setHeader("Pragma", "no-cache");
resp.setContentType("image/jpeg");
String capText = this.kaptchaProducer.createText();
req.getSession().setAttribute(this.sessionKeyValue, capText);
req.getSession().setAttribute(this.sessionKeyDateValue, new Date());
BufferedImage bi = this.kaptchaProducer.createImage(capText);
ServletOutputStream out = resp.getOutputStream();
ImageIO.write(bi, "jpg", out);
}
}
web.xml
<servlet>
<servlet-name>KaptchaServlet</servlet-name>
<servlet-class>top.qaqaq.servlet.MyKaptchaServlet</servlet-class>
</servlet>a
<servlet-mapping>
<servlet-name>KaptchaServlet</servlet-name>
<url-pattern>/kaptcha.jpg</url-pattern>
</servlet-mapping>