当前位置: 移动技术网 > IT编程>开发语言>Java > JavaWeb中HttpSession中表单的重复提交示例

JavaWeb中HttpSession中表单的重复提交示例

2019年07月22日  | 移动技术网IT编程  | 我要评论
表单的重复提交 重复提交的情况: ①. 在表单提交到一个 servlet,而 servlet 又通过请求转发的方式响应了一个 jsp(html)页面,此时地

表单的重复提交

  • 重复提交的情况:

①. 在表单提交到一个 servlet,而 servlet 又通过请求转发的方式响应了一个 jsp(html)页面,此时地址栏还保留着 servlet 的那个路径,在响应页面点击 “刷新”。

②. 在响应页面没有到达时,重复点击 “提交按钮”

③. 点击返回,再点击提交

  • 不是重复提交的情况:点击 “返回”,“刷新” 原表单页面,再点击提交。
  • 如何避免表单的重复提交:在表单中做一个标记,提交到 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中表单的重复提交示例,希望对大家有所帮助

如您对本文有疑问或者有任何想说的,请 点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网