首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Struts Token 機制防止表單重複提交:原理與實戰完整指南

     編輯:Java 相關知識

表單重複提交是 Web 開發常見問題,可能導致重複訂單、重複扣款等嚴重後果。Struts 內建的 Token(令牌)機制提供簡單有效的解決方案。本文深入解析 Token 原理、核心 API 使用、實戰整合範例與基礎類封裝技巧。

Token 機制核心原理

  1. 產生階段:伺服器在處理請求前,將請求中的 Token 值與 Session 中儲存的 Token 比對。
  2. 驗證通過:若比對一致,處理業務邏輯。
  3. 更新階段:回應前產生新 Token,同時更新 Session 並透過隱藏欄位傳回客戶端:
    <input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="...">
  4. 防重複邏輯:使用者若按「上一頁」重新提交,舊 Token 與新 Session Token 不符,判定為重複提交並攔截。

核心 API 速查

方法用途
saveToken(request)在請求/Session 中產生並儲存新 Token,同時輸出至表單隱藏欄位
isTokenValid(request, true)驗證 Token 有效性,true 表示驗證後重置 Token
resetToken(request)手動重置 Session 中的 Token

實戰範例:論壇發文系統

Action 類別實作


public class SubjectAction extends BaseDispatchAction {
    // 步驟 1:進入新增頁面時產生 Token
    public ActionForward add(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response) {
        saveToken(request); // 關鍵:必須在 forward 到 JSP 前呼叫
        return mapping.findForward("add"); // 轉向 subjectAdd.jsp
    }

    // 步驟 2:提交表單時驗證 Token
    public ActionForward insert(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response) {
        if (isTokenValid(request, true)) {
            // 正常提交:執行資料庫插入
            // saveData(...);
            return mapping.findForward("success");
        } else {
            // 重複提交:記錄日誌、顯示錯誤訊息
            saveToken(request); // 重置 Token 讓使用者可再次嘗試
            log.error("重複提交!");
            saveError(request, new ActionMessage("error.repeatSubmit"));
            return mapping.findForward("error");
        }
    }
}

JSP 表單頁面


<html:form action="subjectForm.do?method=insert">
    <html:text property="title" />
    <html:textarea property="content" />
    <html:submit property="發表" />
    <html:reset property="重填" />
</html:form>

若 Action 執行了 saveToken(request),產生的 HTML 會自動包含隱藏欄位:


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

進階封裝:基礎類統一控制重複提交

在實際專案中,建議將 Token 控制邏輯封裝於基礎 Action 類別,避免重複程式碼:


public abstract class BaseDispatchAction extends BaseAction {
    protected ActionForward perform(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        
        String methodName = request.getParameter(mapping.getParameter());
        if (methodName == null) methodName = "list";

        // 統一控制:add 產生 Token,insert 驗證 Token
        if ("add".equals(methodName)) {
            saveToken(request);
        } else if ("insert".equals(methodName)) {
            if (!isTokenValid(request, true)) {
                resetToken(request);
                saveError(request, new ActionMessage("error.repeatSubmit"));
                log.error("重複提交!");
                return mapping.findForward("error");
            }
        }
        return dispatchMethod2(mapping, form, request, response, methodName);
    }
}

適用場景與注意事項

  • 主要適用:資料庫寫入操作(新增、修改、刪除),特別是「新增」類操作。
  • 查詢/刪除/修改:通常透過 ID 定位資料,重複提交風險較低,但視業務需求可選擇性啟用。
  • 必要條件:必須在前置動作(如 add)呼叫 saveToken,後續驗證動作(如 insert)才能正常運作。
  • Session 依賴:Token 儲存於 Session,確保應用伺服器支援 Session 複製(叢集環境需注意)。

總結

Struts Token 機制以「伺服器端產生、客戶端攜帶、比對驗證、動態更新」的簡潔流程,有效解決重複提交問題。配合基礎類封裝,可將防重複邏輯從業務代碼中剝離,實現乾淨、可維護的防禦性程式設計。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved