struts token令牌機制

來源:互聯網
上載者:User

利用Struts同步令牌(Token)機制來解決Web應用中的重複提交問題。該方法的基本原理是:伺服器端在處理到達的request之前,會將request中的Token值與儲存在目前使用者session中的令牌值進行比較,看是否匹配。在處理完該request後,且在response發送給用戶端之前,將會產生一個新的 Token,該Token除傳給用戶端以外,也會將使用者session中儲存的舊的Token進行替換。這樣,如果使用者會退到剛才的提交頁面並再次提交的話,用戶端傳過來的Token值和伺服器端的不一致,從而有效地防止了重複提交地發生。

  struts的Token機制實際上就是通過使用者提交表單時,比較request中的請求參數“org.apache.struts.taglib.html.TOKEN”的值與當前會話中的屬"org.apache.struts.action.TOKEN"的值是否相等,相等則是正常提交,不等則為重複提交。

   下面我們看下一個完整的操作流程,這樣便於理解:
   首先我們要明白,重複提交是發生在什麼情況下的,什麼情況下需要處理重複提交。我們所要解決的重複提交一般是考慮使用者新插入一條記錄的情形,對於修改記錄的重複提交一般不考慮,因為修改記錄本身記錄就存在ID,重複提交也只不過是重複更新資料庫同一記錄而已,對資料的正確性不會有影響。如果新插入一條記錄不對重複提交進行處理的話,那麼就會在資料庫中重複插入同一記錄,這樣會在資料庫產生冗餘的重複記錄。當我們要插入一條記錄時,會分二步走。第一步我們要開啟新增記錄的頁面。第二步,我們會在開啟的頁面中填寫相關資訊,然後提交,這個時候提交才算完成。
第一步:假如我們開啟新增記錄這個操作由add方法完成,代碼如下:
public ActionForward add(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response) { 
  this.saveToken(request);//這個方法就是產生令牌值,struts已有的方法 
  return mapping.findForward("add");//返回新增頁面

}
通過調用saveToken(request),產生一個token值。(註:每次調用saveToken方法產生的token值都不同)然後在記錄新增頁面中的<html:form>內部增加一個隱含表單欄位,形式如下:
<div>

<input type="hidden" name="org.apache.struts.taglib.html.TOKEN"

value="8b2d950f23b02c527988a14171254025">

</div>
然後再把token值"8b2d950f23b02c527988a14171254025"儲存到當前會話中,也就是 session.setAttribute( "org.apache.struts.action.TOKEN","8b2d950f23b02c527988a14171254025");

第二步:假如我們提交這個頁面資料由save方法完成,代碼如下:
public ActionForward save(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response) { 
  if (this.isTokenValid(request)) {//正常提交    this.resetToken(request);//清空當前會話中的token值
   return mapping.findForward("success");//返回儲存成功頁面
  } else {//重複提交   
   this.saveToken(request);//註:此方法在這裡可要也可不要。  
   return mapping.findForward("fail");//返回重複提交提示資訊頁面
  }

}
判斷是不是重複提交關鍵是isTokenValid(request)這個方法,這個方法由struts提供,如果返回結果為true則表示正常提交,false則為重複提交。isTokenValid(request)這個方法實際上主要做了三件事,
1.判斷當前會話是否到期,如果到期,直接返回false
  HttpSession session = request.getSession(false);
        if (session == null) {
            return false;
        }
2.然後再判斷當前會話中是否存在令牌屬性"org.apache.struts.action.TOKEN",如果不存在,返回false
  String saved =(String) session.getAttribute("org.apache.struts.action.TOKEN");
        if (saved == null) {
            return false; 為什麼令牌屬性"org.apache.struts.action.TOKEN"會不存在呢,那是因為當使用者正常提交後,會調用this.resetToken(request);//清空當前會話中的token值。也就是說resetToken(request)方法中調用了 session.removeAttribute("org.apache.struts.action.TOKEN");

當使用者重複提交時,我說了"this.saveToken(request);//此方法在這裡可要也可不要。",下面我們分

析下,如果不調用這個方法,會話中就不會再重新儲存token值,那麼再重新整理的時候,session中的token
值總是為null,isTokenValid(request)直接返回false,如果調用this.saveToken(request)的話,

session中會重新添加token屬性值。這個時候isTokenValid(request)會進行下面第三步的判斷。
3.從當前會話中取得token的值與當前request中得到的token值比較,相同返回true,不同返回false
  String token = request.getParameter("org.apache.struts.taglib.html.TOKEN");
        if (token == null) {
            return false;         return saved.equals(token);

如果是重複重新整理,那麼每次request中的令牌值都是一樣的,但每次重新整理當前會話中的令牌值都被重新替換了,所以會返回false

註:使用struts的表單提交Token機制時,提交的表單一定要寫成<html:form></html:form>這種形式,如果寫成<form></form>這種形式的話,儘管調用saveToken(request)方法也不會在當前的<form></form>裡面產生隱含表單,最終的結果都是"重複提交".

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.