#####前言 之前在不少p2p网站中,都有新手领取红包的活动。这样的红包连接或多或少都有不少的漏洞,就是表单能够重复提交。这样的话,对那些p2p网站或者其余相似的网站形成很大的损失。Fiddler你们都不陌生吧,就是一个抓包软件。咱们先拦截url请求,Shift+R,填入压力测试的次数,而后释放,就会形成不少次的url访问请求,这样的结果很容易形成表单重复提交。那么咱们的今天主题就是如何使用Session和Token防止表单重复提交安全
#####表单重复提交例子 在咱们写网站的时候,确定写过留言板的功能,可是确定对重复提交留言的恶性行为没有进行一些安全措施。 服务器
咱们利用Fiddler这一款抓包软件,能够进行压力测试,模拟屡次url请求。就会形成如下状况,留言板被恶性刷屏。session
#####如何进行防止表单重复提交 其实很简单的,咱们只须要生成一个惟一的token,分别放进客户端的表单里和服务器的session中进行了。当咱们发起请求时,只须要判断session中的token(如下简称serverToken)和客户端表单里的token(如下简称clientToken)是否相等。 若是severToken==null,clientToken==null 还有 serverToken不等于clientToken,那么就说明表单被重复提交了。反之,若是serverToken==clientToken,就说明表单没有被重复提交,当咱们进行了一系列须要的操做后,就能够清除session中的token了。dom
#####具体代码jsp
<% String token=CommonUtils.makeToken(); request.getSession().setAttribute(token,token); %>
public String uploadPhoto(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String result=null; String clientToken=request.getParameter("token"); String serverToken=(String)request.getSession().getAttribute(clientToken); if(!isRepeatCommit(serverToken, clientToken)){ result="请不要重复提交"; request.getSession().setAttribute("result",result); return "/result.jsp"; } request.getSession().removeAttribute(clientToken); }
/** * * @param serverToken * @param clientToken * @return * 若是没有重复提交 返回true, 若是重复提交 返回fasle */ public boolean isRepeatCommit(String serverToken,String clientToken){ MyLog.i(TAG, "serverToken="+serverToken+",clientToken="+clientToken); if(serverToken==null){ return false; } if(clientToken==null){ return false; } if(!clientToken.equals(serverToken)){ return false; } return true; }
#####效果图 我本身写了一个图片上传的demo,就来测试一下是否能防止重复提交吧post
手动测试完毕了,内心确定是美滋滋了。那么咱们用Fiddler来测试一下吧,咱们来模拟一下压力测试。测试
#####发现的问题 写这边简文的时候,我也看到其余大牛写的博客。在底下的评论也发现了一个存在的问题。就是打开2个上传图片的网页,在第一个网页上传到了照片,提示"上传成功"。而后在打开第二个网页再上传图片,就会提示"请不要重复提交"。这是什么问题形成的呢?其实仔细想一下就会发现, 当第一个网站上传图片成功后,就会清除Session中的token值,此时的serverToken=null了。就会形成第二个网站上传图片时候,serverToken=null和serverToken!=clientToken,那么确定会提示"请不要重复提交"。网站
#####解决方案 看到这里,大家估计还有疑问?那么就想一下为何我要生成惟一的Token。咱们这个Token是每一次用户请求的标识。咱们只须要serverToken在Session中的属性值设置为惟一的Token便可。就不会发生刚才的状况。url
String token=CommonUtils.makeToken(); request.getSession().setAttribute(token,token); %>