Struts中利用同步令牌(Token)解決重複提交的問題

在某些情況下,如果用戶對一個HTML表單重複提交,Web應用應該必須能夠判斷用戶的重複提交行爲,以做相應的處理。

Struts給出了一個參考實現。org.apache.struts.action.Action類中提供了一系列和Token有關的方法:

1.protected boolean isTokenVali(javax.servlet.http.HttpServletRequest request)
判斷存儲在當前用戶會話中的令牌值和請求參數中的令牌值是否匹配,如果匹配就返回true,否則返回false.

2.protected void resetToken(javax.servlet.http.HttpServletRequest request)
從當前session中刪除令牌值。

3. protected void saveToken(javax.servlet.http.HttpServletRequest request)
創建一個新令牌,並把他保存在session範圍內。

提示:具體的Token處理邏輯是org.apache.struts.util.TokenProcesor類完成的,大家可以反編譯看看這個類的處理邏輯。它的generateToken(request)方法根據用戶會話ID和當前的系統時間來生成一個唯一的令牌值。

流程:
比如一個註冊流程,在用戶請求註冊頁面之前,是由一個Action轉發給到這個註冊頁面,在這個Action中加入saveToken(request)方法,創建一個Token,並把它保存在session中。然後轉發給註冊頁面。在註冊頁面的<html:form>標籤的處理類會判斷session中是否存在Token,如果存在就在表單中生成一個隱藏域,隱藏域的值就是利用Struts的Token機制算出來的那個值。當用戶接收到註冊頁面後就會發現在FORM表單中存在的Token的隱藏域。在用戶提交了註冊信息到另一個Action中時,在這個Action中用isTokenValid(request)來判斷是否是重複提交,如果用戶是第一次提交表單返回true,如果用戶通過瀏覽器返回按扭,返回該頁再次提交則返回false;進行錯誤處理。

例子:Action1:

Java代碼 複製代碼
  1. public class RegAction extends Action {   
  2.   
  3.  public ActionForward execute(   
  4.   ActionMapping mapping,   
  5.   ActionForm form,   
  6.   HttpServletRequest request,   
  7.   HttpServletResponse response) {   
  8.   //調用方法生成Token   
  9.      saveToken(request);    
  10.   // TODO Auto-generated method stub   
  11.   return mapping.findForward("register");   
  12.  }   
  13. }  
public class RegAction extends Action {

 public ActionForward execute(
  ActionMapping mapping,
  ActionForm form,
  HttpServletRequest request,
  HttpServletResponse response) {
  //調用方法生成Token
     saveToken(request); 
  // TODO Auto-generated method stub
  return mapping.findForward("register");
 }
}


Action1轉發給JSP頁面:

Java代碼 複製代碼
  1. <html:form action="/tokenAction.do" method="poset">   
  2. <html:submit>Submit</html:submit>   
  3. </html:form>  
<html:form action="/tokenAction.do" method="poset">
<html:submit>Submit</html:submit>
</html:form>


在這裏會自動生成Token的隱藏域:
Java代碼 複製代碼
  1. <input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="164fcc77cafd18db1011da3d8ab868e5">  
<input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="164fcc77cafd18db1011da3d8ab868e5">

Action2: jsp頁面提交給過來請求

Java代碼 複製代碼
  1. if(!isTokenValid(request))   
  2.   {   
  3.    System.out.println("重複提交TokenAction");   
  4.    saveToken(request);   
  5.    return (new ActionForward(mapping.getInput()));   
  6.   }   
  7.   else  
  8.   {   
  9.    resetToken(request);   
  10.    System.out.println("重新設置Token!   TokenAction");   
  11.   }  
if(!isTokenValid(request))
  {
   System.out.println("重複提交TokenAction");
   saveToken(request);
   return (new ActionForward(mapping.getInput()));
  }
  else
  {
   resetToken(request);
   System.out.println("重新設置Token!   TokenAction");
  }

判斷是否是重複提交,如果重複提交就轉發到默認在struts-config.xml中爲Action2配置的錯誤頁面中,並重新建立一個Token。如果不是重複提交就就從當前session中刪除Token.
OK,就是這些了,如果你的應用中可以返回一個錯誤頁面,那麼你也可以在filter中應用Token這些方法,只不過需要對struts的jar包進行反編譯,拿到自己的類中來用。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章