Struts 內建 Token 機制有效防止表單重複提交 (如論壇連點發帖)。本文詳細講解 Token 生成、驗證、配置全流程與關鍵細節。
// 顯示發帖頁面
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");
}
}
}
<%@ 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>
關鍵:必須使用 `
<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>
| 問題 | 原因 | 解決 |
|---|---|---|
| Token 總是驗證失效 | 未使用 `| 檢查標籤庫引入、Action 執行順序、Session timeout 設定 | |
| 刷新頁面 Token 失效 | 正常行為:`saveToken()` 只在首次進入頁面執行 | 刷新屬於重複提交預防範圍,或使用 PRG 模式 (Post-Redirect-Get) |
| Ajax 提交無 Token | 手動在請求頭/參數添加 Token 值 | JS 讀取隱藏欄位值:`$('input[name="org.apache.struts.taglib.html.TOKEN"]').val()` |
public ActionForward execute(...) {
if (!isTokenValid(request, true)) return mapping.findForward("duplicate");
// 業務處理...
saveToken(request); // 重新生成 Token 供下一步
return new ActionForward("/askok.do", true); // Redirect 而非 Forward
}
Redirect 後瀏覽器地址欄顯示處理頁面,刷新不會重複提交,結合 Token 雙重保險。