JavaWeb의 HttpSession 양식 중복 제출 예

양식 중복 제출
  • 중복 제출 상황:
  • ①. 양식을 Servlet에 제출하고 Servlet은 전송을 요청하는 방식으로 JSP(HTML) 페이지에 응답합니다. 주소 표시줄에는 Servlet의 경로가 남아 있습니다. 응답 페이지에서 "새로 고침"을 누르십시오.
    ②. 응답 페이지가 도착하지 않았을 때 "제출 버튼"을 반복 클릭합니다
    ③. 반환 클릭, 제출 클릭
  • 중복 제출이 아닌 경우: "되돌아오기", "원본 폼 페이지 새로 고침"을 클릭하고 제출을 클릭하십시오
  • 표의 중복 제출을 피하는 방법: 표에 표시를 하고 Servlet에 제출할 때 표식이 존재하고 미리 정의된 표식과 동일한지 확인하고, 일치하지 않으면 요청을 수리하고, 표식을 삭제하며, 일치하지 않거나 표식이 없으면 "중복 제출"알림에 직접 응답합니다
  • ① 숨겨진 영역만 제공하면 안 됩니다:
    ② 태그를 Request에 넣으면 실행되지 않습니다. 폼 페이지를 새로 고침하면 request는 삭제되고 폼을 제출하면 새로운 request입니다.
    ③ 세션에 태그를 넣으면
    1. 원본 폼 페이지에서 무작위 값 token 생성
    2. 원본 폼 페이지에서 token 값을session 속성에 넣기
    3. 원래 폼 페이지에서 Token 값을 숨겨진 영역에 넣기
    4. 대상의 Servlet에서: 세션과 숨겨진 도메인의 token 값을 가져옵니다.
    두 값이 일치하는지 비교하고, 요청을 수리하고, 세션 영역의 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();
      }
    }
    위에서 말한 것은 편집자가 여러분께 소개한 자바 웹의 HttpSession에서 폼의 중복 제출 예시입니다. 여러분께 도움이 되었으면 합니다. 만약에 궁금한 것이 있으면 저에게 메시지를 남겨 주십시오. 편집자는 제때에 여러분에게 회답할 것입니다.여기에서도 저희 사이트에 대한 지지에 감사드립니다!

    좋은 웹페이지 즐겨찾기