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);
 %>
相關文章
相關標籤/搜索