防止表单重复提交
2016-06-19 22:30
267 查看
在Web开发中表单的重复提交是很严重的问题,重复提交成功会产生垃圾数据消耗不必要的资源,更严重的是如果遇到恶意刷库的情况垃圾数据更是数不胜数。在正常使用过程中产生重复提交的情况也有多重情况:鼠标连击、回退提交、刷新提交、网络延迟用户重复提交等。
防止重复提交的方法分两大类就是客户端、服务端(这是废话了)。客户端主要是用js对按钮的限制,一次点击后屏蔽按钮或者是直接跳转等待页面,服务端思路为客户端加token进行验证。客户端就不做详细介绍,主要介绍服务端的控制。
优点:
不占用服务器资源
实施起来简单,易上手
缺点:
容易伪造(防君子不防小人)
占用网络资源(或许不是那么明显)
详细介绍一下客户端分布存储在Form表单中和Cookie中的情况。
客户端的实现如下:
View Code
整个示例源码:
https://github.com/monkeyming/AvoidDuplicateSubmission
参考:
http://blog.csdn.net/h183288132/article/details/50184199
防止重复提交的方法分两大类就是客户端、服务端(这是废话了)。客户端主要是用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
相关文章推荐
- csdn待改进点之19------>为什么这里的功能不是取消收藏? 这种体验让人抓狂
- 列表和元组
- 自定义控件起步(四)--自定义验证码(下)
- 启发孩子的几个小问题1
- 产生死锁的原因
- js在ie下打开对话窗口的方式
- code1064 虫食算
- Android 项目在Eclipse中的目录结构
- 《人性的弱点》卡耐基
- 20145302张薇《Java程序设计》第十六周课程总结
- iOS新闻客户端开发教程8-加载更多和新闻详情
- Android 四大组件 —— 活动(使用Intent 实现活动的显示跳转)
- JavaWeb应用中使用JavaMail发送邮件
- Leetcode-4. Median of Two Sorted Arrays
- 【51CTO学院三周年】毕业三周年
- Android 四大组件 —— 活动(活动的隐式跳转)
- hadoop2.4.1伪分布式搭建基本流程
- Python 列表(List)
- 第16周课程总结
- 一些操作系统安全设置