JavaWeb学习(1) 使用Session和Token防止表单重复提交

#####前言 之前在不少p2p网站中,都有新手领取红包的活动。这样的红包连接或多或少都有不少的漏洞,就是表单能够重复提交。这样的话,对那些p2p网站或者其余相似的网站形成很大的损失。Fiddler你们都不陌生吧,就是一个抓包软件。咱们先拦截url请求,Shift+R,填入压力测试的次数,而后释放,就会形成不少次的url访问请求,这样的结果很容易形成表单重复提交。那么咱们的今天主题就是如何使用Session和Token防止表单重复提交安全


#####表单重复提交例子 在咱们写网站的时候,确定写过留言板的功能,可是确定对重复提交留言的恶性行为没有进行一些安全措施。 服务器

Paste_Image.png

咱们利用Fiddler这一款抓包软件,能够进行压力测试,模拟屡次url请求。就会形成如下状况,留言板被恶性刷屏。session

Paste_Image.png


#####如何进行防止表单重复提交 其实很简单的,咱们只须要生成一个惟一的token,分别放进客户端的表单里和服务器的session中进行了。当咱们发起请求时,只须要判断session中的token(如下简称serverToken)和客户端表单里的token(如下简称clientToken)是否相等。 若是severToken==null,clientToken==null 还有 serverToken不等于clientToken,那么就说明表单被重复提交了。反之,若是serverToken==clientToken,就说明表单没有被重复提交,当咱们进行了一系列须要的操做后,就能够清除session中的token了。dom


#####具体代码jsp

  • 生成惟一的Token public static String makeToken(){ String token=(System.currentTimeMillis()+new Random().nextInt(999999999))+""; try { MessageDigest mDigest=MessageDigest.getInstance("md5"); byte[] md5=mDigest.digest(token.getBytes()); BASE64Encoder encoder=new BASE64Encoder(); return encoder.encode(md5); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); }}
  • Jsp代码
<%
 String token=CommonUtils.makeToken();
 request.getSession().setAttribute(token,token);
 %>

 
 
 
 
上传图片:
描 述:

  • Serlvet代码
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

Paste_Image.png
首先手动测试一下,是否能防止重复提交

Paste_Image.png
咱们上传成功后,再次刷新地址栏,会发现已经防止了表单重复提交

Paste_Image.png

手动测试完毕了,内心确定是美滋滋了。那么咱们用Fiddler来测试一下吧,咱们来模拟一下压力测试。测试

Paste_Image.png
咱们从Fiddler看到返回结果,内心更是美滋滋了。已经成功防止了表单重复提交不安全的行为了。

Paste_Image.png

#####发现的问题 写这边简文的时候,我也看到其余大牛写的博客。在底下的评论也发现了一个存在的问题。就是打开2个上传图片的网页,在第一个网页上传到了照片,提示"上传成功"。而后在打开第二个网页再上传图片,就会提示"请不要重复提交"。这是什么问题形成的呢?其实仔细想一下就会发现, 当第一个网站上传图片成功后,就会清除Session中的token值,此时的serverToken=null了。就会形成第二个网站上传图片时候,serverToken=null和serverToken!=clientToken,那么确定会提示"请不要重复提交"。网站


#####解决方案 看到这里,大家估计还有疑问?那么就想一下为何我要生成惟一的Token。咱们这个Token是每一次用户请求的标识。咱们只须要serverToken在Session中的属性值设置为惟一的Token便可。就不会发生刚才的状况。url

 String token=CommonUtils.makeToken();
 request.getSession().setAttribute(token,token);
 %>
相关文章
相关标签/搜索