您好,登錄后才能下訂單哦!
表單的重復提交
①. 在表單提交到一個 Servlet,而 Servlet 又通過請求轉發的方式響應了一個 JSP(HTML)頁面,此時地址欄還保留著 Servlet 的那個路徑,在響應頁面點擊 “刷新”。
②. 在響應頁面沒有到達時,重復點擊 “提交按鈕”
③. 點擊返回,再點擊提交
①僅提供一個隱藏域不行:<input type="hidden" name="token" value="lsy">
②把標記放在 Request 中 , 行不通,表單頁面刷新后,request 已經被銷毀,再提交表單是一個新的 request 的。
③把標記放在 Session 中,可以
1. 在原表單頁面,生成一個隨機值 token
2. 在原表單頁面,把 token 值放入 session 屬性中
3. 在原表單頁面,把 token 值放入到隱藏域
4. 在目標的 Servlet 中:獲取 session 和隱藏域中的 token 值
比較兩個值是否一致,受理請求,且把 session 域中的 token 屬性清除,若不一致,則直接響應提示頁面:“重復提交”
我們可以通過 Struts1 中寫好的類 TokenProcessor 來重構代碼, 面向組件編程
package com.lsy.javaweb; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class TokenProcessor { private static final String TOKEN_KEY = "TOKEN_KEY"; private static final String TRANSACTION_TOKEN_KEY = "TRANSACTION_TOKEN_KEY"; /** * The singleton instance of this class. */ private static TokenProcessor instance = new TokenProcessor(); /** * The timestamp used most recently to generate a token value. */ private long previous; /** * Protected constructor for TokenProcessor. Use * TokenProcessor.getInstance() to obtain a reference to the processor. */ protected TokenProcessor() { super(); } /** * Retrieves the singleton instance of this class. */ public static TokenProcessor getInstance() { return instance; } /** * <p> * Return <code>true</code> if there is a transaction token stored in the * user's current session, and the value submitted as a request parameter * with this action matches it. Returns <code>false</code> under any of the * following circumstances: * </p> * * <ul> * * <li>No session associated with this request</li> * * <li>No transaction token saved in the session</li> * * <li>No transaction token included as a request parameter</li> * * <li>The included transaction token value does not match the transaction * token in the user's session</li> * * </ul> * * @param request * The servlet request we are processing */ public synchronized boolean isTokenValid(HttpServletRequest request) { return this.isTokenValid(request, false); } /** * Return <code>true</code> if there is a transaction token stored in the * user's current session, and the value submitted as a request parameter * with this action matches it. Returns <code>false</code> * * <ul> * * <li>No session associated with this request</li> * <li>No transaction token saved in the session</li> * * <li>No transaction token included as a request parameter</li> * * <li>The included transaction token value does not match the transaction * token in the user's session</li> * * </ul> * * @param request * The servlet request we are processing * @param reset * Should we reset the token after checking it? */ public synchronized boolean isTokenValid(HttpServletRequest request, boolean reset) { // Retrieve the current session for this request HttpSession session = request.getSession(false); if (session == null) { return false; } // Retrieve the transaction token from this session, and // reset it if requested String saved = (String) session.getAttribute(TRANSACTION_TOKEN_KEY); if (saved == null) { return false; } if (reset) { this.resetToken(request); } // Retrieve the transaction token included in this request String token = request.getParameter(TOKEN_KEY); if (token == null) { return false; } return saved.equals(token); } /** * Reset the saved transaction token in the user's session. This indicates * that transactional token checking will not be needed on the next request * that is submitted. * * @param request * The servlet request we are processing */ public synchronized void resetToken(HttpServletRequest request) { HttpSession session = request.getSession(false); if (session == null) { return; } session.removeAttribute(TRANSACTION_TOKEN_KEY); } /** * Save a new transaction token in the user's current session, creating a * new session if necessary. * * @param request * The servlet request we are processing */ public synchronized String saveToken(HttpServletRequest request) { HttpSession session = request.getSession(); String token = generateToken(request); if (token != null) { session.setAttribute(TRANSACTION_TOKEN_KEY, token); } return token; } /** * Generate a new transaction token, to be used for enforcing a single * request for a particular transaction. * * @param request * The request we are processing */ public synchronized String generateToken(HttpServletRequest request) { HttpSession session = request.getSession(); return generateToken(session.getId()); } /** * Generate a new transaction token, to be used for enforcing a single * request for a particular transaction. * * @param id * a unique Identifier for the session or other context in which * this token is to be used. */ public synchronized String generateToken(String id) { try { long current = System.currentTimeMillis(); if (current == previous) { current++; } previous = current; byte[] now = new Long(current).toString().getBytes(); MessageDigest md = MessageDigest.getInstance("MD5"); md.update(id.getBytes()); md.update(now); return toHex(md.digest()); } catch (NoSuchAlgorithmException e) { return null; } } /** * Convert a byte array to a String of hexadecimal digits and return it. * * @param buffer * The byte array to be converted */ private String toHex(byte[] buffer) { StringBuffer sb = new StringBuffer(buffer.length * 2); for (int i = 0; i < buffer.length; i++) { sb.append(Character.forDigit((buffer[i] & 0xf0) >> 4, 16)); sb.append(Character.forDigit(buffer[i] & 0x0f, 16)); } return sb.toString(); } }
以上所述是小編給大家介紹的JavaWeb中HttpSession中表單的重復提交示例,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對億速云網站的支持!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。