您的位置:首页 > 其它

防止表单重复提交

2016-06-19 22:30 267 查看
  在Web开发中表单的重复提交是很严重的问题,重复提交成功会产生垃圾数据消耗不必要的资源,更严重的是如果遇到恶意刷库的情况垃圾数据更是数不胜数。在正常使用过程中产生重复提交的情况也有多重情况:鼠标连击、回退提交、刷新提交、网络延迟用户重复提交等。

  防止重复提交的方法分两大类就是客户端、服务端(这是废话了)。客户端主要是用js对按钮的限制,一次点击后屏蔽按钮或者是直接跳转等待页面,服务端思路为客户端加token进行验证。客户端就不做详细介绍,主要介绍服务端的控制。

1、客户端存储

  就是在客户端不同的地方存储两个token,在服务端进行校验。在Form表单中存储一个token利用隐藏域,在Cookie中存储一个(也可以都放到form表单中两个不同的隐藏域)。档form表单提交的时候,对这两个token进行验证,相同则允许提交否则阻止提交。

优点:

  不占用服务器资源

  实施起来简单,易上手

缺点

  容易伪造(防君子不防小人)

  占用网络资源(或许不是那么明显)

详细介绍一下客户端分布存储在Form表单中和Cookie中的情况。

客户端的实现如下:

package cn.simple.token;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
* 服务端用Session存储
*
* @author ldm
* @Date 2016年6月16日
*/
@Service("sessionTokenProcesser")
public class SessionTokenProcesser extends TokenProcesser {

@Autowired
HttpServletResponse response;

@Override
public boolean validToken(HttpServletRequest request) {

String clientToken = getClientToken(request);
if (StringUtils.isEmpty(clientToken)) {
return false;
}
HttpSession session = request.getSession(false);
if (session == null) {
return false;
}
String tokenKey = getTokenKey(request);
Object tokenObj = session.getAttribute(tokenKey);
if(tokenObj==null)
{
rethrow("服务端不存在当前token,请重新请求表单");
}
String serverToken = tokenObj.toString();

session.removeAttribute(tokenKey);
System.out.println("remove server token:" + serverToken);
return clientToken.equals(serverToken);

}

@Override
public String getTokenKey(HttpServletRequest request) {
return getTokenField();
}

@Override
public void saveToken(HttpServletRequest request) {

HttpSession session = request.getSession();
String tokenKey = getTokenKey(request);
Object tokenObj = session.getAttribute(tokenKey);
String token;
if (tokenObj == null) {
token = MakeToken.getInstance().getToken();
// 服务端保存token
session.setAttribute(tokenKey, token);
} else {
token = tokenObj.toString();
}
System.out.println("current token:" + token);
// 写入cookie
Cookie cookie = new Cookie(getTokenField(), token);
response.addCookie(cookie);
}

private void rethrow(String message) {
RuntimeException e = new RuntimeException(message);
throw e;
}

@Override
public String getClientToken(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
if (cookies == null) {
rethrow("没有读取到客户端的cookie");
return null;
}

for (Cookie cookie : cookies) {
if (cookie.getName().equals(getTokenKey(request))) {
String cookieValue = cookie.getValue();
return cookieValue;
}
}
rethrow("客户端cookie中没有存储token");
return null;
}

}


View Code
整个示例源码:
https://github.com/monkeyming/AvoidDuplicateSubmission
参考:
http://blog.csdn.net/h183288132/article/details/50184199
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: