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

JSP 防止表單重複提交:基於 Session Token 的服務端驗證方案

     編輯:關於JSP

用戶雙擊提交按鈕、瀏覽器刷新/後退導致的表單重複提交,可能造成重複訂單、重複扣款等嚴重業務問題。本文講解基於 Session Token 的服務端幂等性校驗方案。

核心原理:Token 生命周期管理

  1. 頁面加載階段:服務端生成唯一 Token,存入 Session,同時寫入表單隱藏域。
  2. 表單提交階段:服務端比對請求參數 Token 與 Session Token。
    • 一致 → 業務處理,立即清除/更新 Session Token。
    • 不一致/為空 → 拒絕處理,提示「重複提交」。
  3. 後續請求:Session Token 已失效,任何重複提交均被攔截。

完整代碼實現

1. 表單頁

<%@ page contentType="text/html;charset=GB2312" %>
<html><head><title>提交頁面</title></head><body>
<% 
// 生成 Token 存入 Session
String token = UUID.randomUUID().toString();
session.setAttribute("submitToken", token);
%>
<form action="ServerSubmit.jsp" method="post">
  <input type="hidden" name="token" value="<%=token%>" />
  <input type="checkbox" name="check_1" checked="true" />人在江湖
  <input type="submit" name="submitok" value="提交" />
</form>
</body></html>

2. 處理頁

<%@ page contentType="text/html;charset=GB2312" %>
<html><head><title>服務器端程序</title></head><body>
<%
String clientToken = request.getParameter("token");
String serverToken = (String) session.getAttribute("submitToken");

if (serverToken == null || !serverToken.equals(clientToken)) {
    out.println("重複提交或無效請求!");
} else {
    // 業務邏輯處理...
    out.println("正常業務處理完成!");
    // 關鍵:處理後立即移除 Token,防止重複
    session.removeAttribute("submitToken");
}
%>
</body></html>

進階優化:Filter 統一攔截

@WebFilter("/*")
public class TokenFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        
        if ("POST".equalsIgnoreCase(request.getMethod())) {
            String token = request.getParameter("token");
            String sessionToken = (String) request.getSession().getAttribute("submitToken");
            
            if (sessionToken == null || !sessionToken.equals(token)) {
                response.sendRedirect("duplicate_submit.jsp");
                return;
            }
            request.getSession().removeAttribute("submitToken");
        }
        chain.doFilter(req, resp);
    }
}

注意事項

  • Token 必須具備不可預測性(使用 UUID/安全隨機數)。
  • 分布式環境需共享 Session(Redis Session)或使用 JWT/分佈式鎖。
  • GET 請求不應修改服務端狀態,天然幂等,無需 Token。
  • 前端配合:提交後禁用按鈕、PRG 模式(Post-Redirect-Get)防刷新重複。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved