天天看點

isTokenValid防止表單重複送出

Struts中用isTokenValid(request,boolean)方法來防止重新整理時表單重複送出!   Struts在你每次通路Action的時候,根據使用者會話ID和目前系統時間對于每個會話生成一個唯一令牌,儲存在你的Session裡面,如果你在Action裡的函數裡面,使用了saveToken(request),那麼這個令牌也會儲存在這個Action所Forward到的jsp所生成的靜态頁面裡。  如果你在你Action的方法裡使用了isTokenValid,那麼Struts将會從你的request裡面去擷取這個令牌值,然後和Session裡的令牌值做比較,如果兩者相等,就不是重複送出,如果不相等,就是重複送出了。

一、基本原理

伺服器端在處理到達的請求之前,會将請求中包含的令牌值與儲存在目前使用者會話中的令牌值進行比較,

看是否比對。在處理完該請求後,且在答複發送給用戶端之前,将會産生一個新的令牌,該令牌除傳給

用戶端以外,也會将使用者會話中儲存的舊的令牌進行替換。這樣如果使用者回退到剛才的送出頁面并再次

送出的話,用戶端傳過來的令牌就和伺服器端的令牌不一緻,進而有效地防止了重複送出的發生。

二、首先介紹一下struts提供的有關令牌的相關方法

protected String generateToken(HttpServletRequest request) 建立一個令牌.

protected boolean isTokenValid(HttpServletRequest request) 檢查令牌是否有效

protected boolean isTokenValid(HttpServletRequest request,Boolean reset) 檢查令牌是否有效,并且重置令牌(如果reset 是true)

protected void resetToken(HttpServletRequest request) 重置令牌

protected void saveToken(HttpServletRequest request) 添加令牌

        //action生成令牌生成令牌方法

 protected String generateToken(HttpServletRequest request) {

       HttpSession session = request.getSession();

       try {

           byte id[] = session.getId().getBytes();

           byte now[] =

               new Long(System.currentTimeMillis()).toString().getBytes();

           MessageDigest md = MessageDigest.getInstance("MD5");

           md.update(id);

           md.update(now);

           return (toHex(md.digest()));

       } catch (IllegalStateException e) {

           return (null);

       } catch (NoSuchAlgorithmException e) {

           return (null);

       }

   }

三、參考樣例

例如:在新增資訊過程中增加防止表單重複送出(進入新增頁面方法名稱add(),儲存資訊方法名稱save())。

1、add()中儲存一個令牌令牌

在進入新增頁面的方法add()中建立令牌,儲存在你的session裡面,這個Action方法add()所進入的jsp新增檔案中将會根據session辨別自動生成一個hidden(隐藏input屬性)展示建立的令牌值。

//add()中的儲存一個令牌代碼

   saveToken(request);

//頁面中生成的hidden代碼:

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

2、save()中進行令牌比較

在save()方法中從request中取出第一步生成的hidden值,如果request中的令牌與session中令牌一緻就說明不是重複送出表單。成功儲存資訊後的跳轉頁面将會儲存一個新的令牌到session中,頁面中hidden值也是新的令牌值。這時在跳轉的頁面中做重新整理操作上一次請求的令牌與第二次請求的令牌值就會不一緻,進而有效地防止了重複送出的發生。

注:如果程式是自動傳回到新增頁面就會重新執行add(),如跳轉到其他頁面比如說list(),那麼list()也要同時加入saveToken(request);重新儲存一個新的令牌

//save()中比較代碼

if (isTokenValid(request, true)) {

     //表單不是重複送出 

            // 完成資訊儲存

     return mapping.findForward("success");

       } else {

     //表單重複送出 

     //其他操作

          return mapping.findForward("submitagain"); 

       }