1. 程式人生 > >利用Token機制解決重複重複提交問題

利用Token機制解決重複重複提交問題



1、isTokenValie方法:
判斷儲存在當前使用者會話中的令牌值和請求引數中的令牌值是否匹配.如果匹配,返回true,反之返回false.只要符合下列情況之一的,就會返回false:
不存在HttpSession物件;
在session範圍內沒有儲存令牌值;
在請求引數中沒有令牌值;
儲存在當前使用者session範圍內的令牌值和請求引數中的令牌值不匹配.

2、resetToken方法:
從當前session範圍內刪除令牌屬性.

3、saveToken方法:
建立一個新的令牌,並把它儲存在當前session範圍內.如果HttpSession不存在,就首先建立一個HttpSession物件.

如何利用上述方法應用令牌機制解決重複提交問題:
以使用者註冊為例:

(一)使用者請求newUser.jsp之前,首先把請求轉發到PrepareAction,


(二)PrepareAction 呼叫saveToken方法,建立一個新的令牌,並將令牌值儲存在當前HttpSession中(新建立的),PrepareAction接著把請求轉發 給newUser.jsp.

(三)newUser.jsp中的<html:form>標籤自動判斷在session範圍內是否存在Token,如果存在,就自動在表單中生成一個包含Token資訊的隱藏欄位,例如: 
<input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="....">

(四)在使用者提交表單後,由InsertUserAction處理請求.在InsertUserAction中,呼叫isTokenValid方法,判斷當前用 戶會話中的令牌值和請求引數中的令牌值是否匹配.如果匹配,就呼叫resetToken方法,刪除Token,然後執行插入資料操作.如果不匹配,返回相 關錯誤提示,進行相關操作.


OK.醬紫就可以有效放置重複提交了.

如何在不使用Struts的前提下利用令牌機制解決重複提交問題:
Struts的令牌機制有幾個要點可以讓我們在普通的JSP/Servlet中解決重複提交問題.

1、提供幾個操作Token的相關方法:
關鍵有三個:
resetToken(HttpServletRequest request)-->重置令牌值.
saveToken(HttpServletRequest request)-->儲存令牌值.
isTokenValid(HttpServletRequest request)-->檢測令牌是否合法.

2、在form表單中增加隱藏域,儲存當前令牌值.

3、在執行永續性資料操作之前呼叫相關方法判斷當前令牌是否合法,之後在進行相關操作.

方法是相同的,只是實現的方式不太一樣.

struts1.1 API關於幾個Token操作方法的說明:

protected    boolean isTokenValid(javax.servlet.http.HttpServletRequest request) 
            Return true if there is a transaction token stored in the user's current session, and the value submitted as a request parameter with this action matches it. 

protected    boolean isTokenValid(javax.servlet.http.HttpServletRequest request, boolean reset) 
            Return true if there is a transaction token stored in the user's current session, and the value submitted as a request parameter with this action matches it. 

protected    void resetToken(javax.servlet.http.HttpServletRequest request) 
            Reset the saved transaction token in the user's session. 

protected    void saveToken(javax.servlet.http.HttpServletRequest request) 
            Save a new transaction token in the user's current session, creating a new session if necessary.

Struts的Token(令牌)機制能夠很好的解決表單重複提交的問題,基本原理是:

伺服器端在處理到達的請求之前,會將請求中包含的令牌值與 儲存在當前使用者會話中的令牌值進行比較,看是否匹配。在處理完該請求後,且在答覆傳送給客戶端之前,將會產生一個新的令牌,該令牌除傳給客戶端以外,也會 將使用者會話中儲存的舊的令牌進行替換。這樣如果使用者回退到剛才的提交頁面並再次提交的話,客戶端傳過來的令牌就和伺服器端的令牌不一致,從而有效地防止了 重複提交的發生。

其實也就是兩點,第一:你需要在請求中有這個令牌值,請求中的令牌值如何儲存,其實就和我們平時在頁面中儲存一些資訊是一樣的,通過隱藏欄位來 儲存,儲存的形式如: 〈input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="6aa35341f25184fd996c4c918255c3ae"〉,這個value是TokenProcessor類中的 generateToken()獲得的,是根據當前使用者的session id和當前時間的long值來計算的。第二:在客戶端提交後,我們要根據判斷在請求中包含的值是否和伺服器的令牌一致,因為伺服器每次提交都會生成新的 Token,所以,如果是重複提交,客戶端的Token值和伺服器端的Token值就會不一致。下面就以在資料庫中插入一條資料來說明如何防止重複提交。

參考:http://www.blogjava.net/yrJavaWorld/archive/2007/10/09/50020.html