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

Struts Token 機制防止重複提交:從原理到實戰完整指南

     編輯:Java 相關知識

Struts 內建 Token 機制有效防止表單重複提交 (如論壇連點發帖)。本文詳細講解 Token 生成、驗證、配置全流程與關鍵細節。

核心流程

  1. 生成 Token:顯示表單頁面的 Action 執行 `saveToken(request)`
  2. 表單攜帶:JSP 使用 `` 自動生成隱藏欄位 ``
  3. 提交驗證:處理提交的 Action 執行 `isTokenValid(request, true)`,`true` 表示驗證後重置 Token
  4. 分支處理:驗證通過 → 業務邏輯;驗證失敗 → 重導提示頁

完整代碼範例

Action 類


// 顯示發帖頁面
public class AskAction extends Action {
  public ActionForward execute(ActionMapping mapping, ActionForm form,
      HttpServletRequest request, HttpServletResponse response) {
    saveToken(request);  // 關鍵:生成 Token 存入 Session
    return mapping.findForward("askPage");
  }
}

// 處理發帖提交
public class AskOkAction extends Action {
  public ActionForward execute(ActionMapping mapping, ActionForm form,
      HttpServletRequest request, HttpServletResponse response) {
    if (isTokenValid(request, true)) {  // 驗證並重置
      // 業務邏輯:儲存發帖內容
      return mapping.findForward("success");
    } else {
      // 重複提交:導向錯誤提示頁
      return mapping.findForward("duplicate");
    }
  }
}

JSP 表單頁面 (ask.jsp)


<%@ taglib uri="https://struts.apache.org/tags-html" prefix="html" %>
<html:form action="/askok.do" method="post">
  <html:textarea property="content" />
  <html:submit value="發表" />
</html:form>

關鍵:必須使用 `` 標籤,普通 `

` 不會生成 Token 隱藏欄位。

struts-config.xml 配置


<action path="/ask" type="com.example.AskAction" 
  forward="/ask.jsp" />

<action path="/askok" type="com.example.AskOkAction" 
  name="askForm" scope="request" input="/ask.jsp">
  <forward name="success" path="/askok.jsp" />
  <forward name="duplicate" path="/duplicate.jsp" />
</action>
  • `name="askForm"` 對應 FormBean,`` 會自動生成 `name="askForm"` 屬性
  • 若 JSP 需 JavaScript 存取表單,可用 `document.askForm` 或 `document.forms['askForm']`

Token 原理深度解析

  • Token 存儲在 Session 中:`session.setAttribute("org.apache.struts.action.TOKEN", token)`
  • 表單提交攜帶 Token 值,`isTokenValid()` 比較 Session Token 與請求 Token
  • `resetToken(request)` 可手動重置 (如驗證失敗後允許再次提交)
  • 多標籤頁場景:同一 Session 共享 Token,切換標籤提交會失效 — 這是設計使然

常見問題與解決

問題原因解決
Token 總是驗證失效未使用 ``、Action 未執行 `saveToken()`、Session 過期檢查標籤庫引入、Action 執行順序、Session timeout 設定
刷新頁面 Token 失效正常行為:`saveToken()` 只在首次進入頁面執行刷新屬於重複提交預防範圍,或使用 PRG 模式 (Post-Redirect-Get)
Ajax 提交無 Token手動在請求頭/參數添加 Token 值JS 讀取隱藏欄位值:`$('input[name="org.apache.struts.taglib.html.TOKEN"]').val()`

進階:PRG 模式配合 Token


public ActionForward execute(...) {
  if (!isTokenValid(request, true)) return mapping.findForward("duplicate");
  // 業務處理...
  saveToken(request);  // 重新生成 Token 供下一步
  return new ActionForward("/askok.do", true); // Redirect 而非 Forward
}

Redirect 後瀏覽器地址欄顯示處理頁面,刷新不會重複提交,結合 Token 雙重保險。

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