您的位置:首页 > 其它

使用session在服务端防止表单重复提交

2018-01-26 18:19 375 查看

相较于在客户端使用js等方式防止用户重复点击或者通过别的方式重复提交表单,在服务端使用session防止表单重复提交更能解决问题。当然前后端结合使用会给用户更好的体验



思路:

1、获取一个独一无二的token(防止重复提交的key),我们这里使用一个自己封装好的方(TokenProccessor),把获取到的token加到session中。

2、新建form.jsp页面。使用servlet将token转发(必须是转发)到form表单页面,在页面上使用隐藏域的方式把后台传来的token放到form标签
<input type="hidden" name="token" value="${token}">
中,提交时随表单一起提交。

3、在后台分三种情况

3.1首先验证传来的token是否为空,为空的情况意思是用户没有通过正常的操作获取到表单,故表单中提交的token为空,这种情况我们认为不合法,此处return false处理。(防盗链也是这么搞得,这里就不细讲了,感兴趣的同学可以自己看看,结合本文,很容易就搞出来了)

3.2验证服务端中session里存的token是否为空(当第一次验证通过后会把session中的token清掉),为空说明已经提交过一次了,所以是重复提交,这里return false处理

3.3验证获取到的token是否与session中的token一致,一致则通过验证提交表单,同时清掉session里的token。下面该干嘛干嘛。不一致的情况就不聊了

思路理清后,下面上代码,顺序都一样的哦。

目录结构



web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
<servlet>
<servlet-name>formSession</servlet-name>

d244
<servlet-class>ser.david.useSessionFormRepeatDemo.FormSession</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>formSession</servlet-name>
<url-pattern>/formSession</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>doformSession</servlet-name>
<servlet-class>ser.david.useSessionFormRepeatDemo.DoFormServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>doformSession</servlet-name>
<url-pattern>/doformSession</url-pattern>
</servlet-mapping>
</web-app>


TokenProccessor.java 使用单例模式

package ser.david.useSessionFormRepeatDemo;

import sun.misc.BASE64Encoder;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

public class TokenProccessor {
/*
单例化
1、构造方法私有
2、自己创建自己对象
3、对外暴露一个方法,可以获取上面自己创建的自己的对象
*/

private TokenProccessor(){};
private static final TokenProccessor instance=new TokenProccessor();
public static TokenProccessor getInstance(){
return instance;
}

public String generatetoken(){
String token=System.currentTimeMillis()+new Random().nextInt()+"";

try {
MessageDigest md=MessageDigest.getInstance("md5");
byte[] md5=md.digest(token.getBytes());
//base64编码
BASE64Encoder encoder=new BASE64Encoder();
return encoder.encode(md5);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
}


FormSession.java

package ser.david.useSessionFormRepeatDemo;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class FormSession extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//产生随机数
TokenProccessor tp=TokenProccessor.getInstance();
String token=tp.generatetoken();

request.getSession().setAttribute("token",token);
request.getRequestDispatcher("/form.jsp").forward(request,response);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}


Form.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/doformSession" method="post">
<input type="hidden" name="token" value="${token}">
用户名:<input type="text" name="username"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>


DoFormServlet.java

package ser.david.useSessionFormRepeatDemo;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//使用session在服务端防止表单重复提交
public class DoFormServlet extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

boolean b=isTokenValid(request);
if (!b){
System.out.println("请不要重复提交");
return;
}

request.getSession().removeAttribute("token");
System.out.println("向数据库中注册数据。。。。。");
}

private boolean isTokenValid(HttpServletRequest request){
String client_token =request.getParameter("token");

if (client_token==null){
return false;
}

String server_token=(String)request.getSession().getAttribute("token");
if (server_token==null){
return false;
}

if (!client_token.equals(server_token)){
return false;
}
return true;
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}


效果图:

1、访问/session,跳转到form.jsp页面、填写并提交



2、可以看到已经提交成功



3、刷新页面或者后退重新点击提交按钮,可以看到表单提交被拦截,后台输出提示信息

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: