重定向后HttpServletRequest对象更改和会话丢弃

时间:2016-08-25 08:35:33

标签: spring spring-mvc tomcat servlets

我一直致力于在我的电子商务应用程序中实施Punchout。我的实现如下:

enter image description here

直到昨天一切正常,然后当重定向到商店前端时,会话开始掉线

我的观察:

重定向发生前HttpServletRequest对象为RequestFacade,但在重定向后,它变为ApplicationHttpRequest。我可以找到包裹在RequestFacade中的ApplicationHttpRequest,但我找不到我在会话中放置的对象。下面是我用来将对象放在会话中的函数。

/**
 * Creates an object of {@link PunchoutSessionDTO} and puts it in
 * the session, making it a punchout session.
 * 
 * @param punchoutTransaction
 *          The {@link PunchoutTransaction} object passed from the 
 *          {@link PunchoutStoreEntryController}.
 * @param session
 *          The {@link HttpSession}.
 */
public void createPunchoutSession(PunchoutTransaction punchoutTransaction, HttpSession session) {

    // Create a PunchoutSessionDTO object.
    PunchoutSessionDTO state = new PunchoutSessionDTO();

    // Initialize it with the variables from the PunchoutTransaction
    // object passed to it.
    state.setBrowserFormPost(punchoutTransaction.getCallbackURL());
    state.setBuyerCookie(punchoutTransaction.getBuyerCookie());
    state.setFromId(punchoutTransaction.getFromId());
    state.setToId(punchoutTransaction.getToId());
    state.setPoTransId(punchoutTransaction.getTransactionId());
    state.setOciPunchout(punchoutTransaction.getTransactionType() == PunchoutTransaction.TYPE_OCI);

    // And put it in the session, so that the session could be
    // identified as a punchout session.
    session.setAttribute("PunchoutState", state);

    // Set the max inactive interval of the session to the value
    // provided in the store property. If such store property is
    // not found, a default of 5 minutes is used.
    /*String vid = punchoutTransaction.getVendorId();
    Integer timeout = PunchoutStorePropertyFactory.getTimeoutPeriod(vid);
    session.setMaxInactiveInterval( (timeout == null ? 5 : timeout) * 60); */

    logger.info("Punchout Session Created for " + punchoutTransaction.getBuyerCookie());
}

一切正常,直到我决定为会话设置超时值。在此之后,问题开始发生。起初,我认为我通过传递setMaxInactiveInterval()的错误值来弄乱它,所以我评论了它。令我惊讶的是,无论如何,会议都被放弃了。

请注意:

  • 我们在Apache Tomcat上使用Windows 8.1
Server version: Apache Tomcat/7.0.54
Server built:   May 19 2014 10:26:15
Server number:  7.0.54.0
OS Name:        Windows 8
OS Version:     6.2
Architecture:   amd64
JVM Version:    1.7.0_51-b13
JVM Vendor:     Oracle Corporation
  • 我们正在使用Spring 2.5。是!我们无法迁移,因为这个应用程序非常庞大(超过10,000个源文件)。

  • URL模式*.po*.html映射到同一个servlet,因此重定向发生在同一个servlet中。

Google搜索:

  1. 为什么HttpServletRequest对象会发生变化。

  2. HttpServletRequest更改为ApplicationHttpRequest

  3. HttpServletRequest to ApplicationHttpRequest

  4. Spring ServletRequest对象更改

  5. 重定向后HttpServletRequest更改

  6. 自从过去3天以来,这个愚蠢的错误让我们感到沮丧。任何帮助,将不胜感激!请指出我所犯的任何愚蠢错误,并且一些与会话处理/管理相关的好提示是最受欢迎的。如果您认为我没有提供足够的信息,请同时指出。谢谢:))

2 个答案:

答案 0 :(得分:1)

是的,我正在回答我自己的问题。我希望详细介绍,以便未来的人可以找到答案。

原来我是一个重定向到绝对路径的白痴。

重定向是关键。

无论您重定向的servlet是驻留在同一个应用程序服务器上,都在同一个应用程序中,或者它甚至共享同一个servlet。 重定向到绝对路径的任何请求都有自己的上下文!因此,为它们创建的请求对象是全新的,并且具有单独的会话。只有在同一porthost和{{1}上发送重定向时,才会维护会话。 }。 如果在同一个应用程序中完成重定向,则使用相对路径使用相对路径是最佳做法

webapp重定向到https://localhost/servlet1.html是非常不同的,即使URL映射到同一个servlet(请注意区别)。

http://localhost/servlet2.html重定向到https://localhost/servlet1.htmlhttps://192.168.x.x/servlet2.html会产生相同的结果。

此处的最佳做法是重定向到相对于您的应用程序的路径 。这将以最有效的方式共享会话对象。 使用https://127.0.0.1/servlet2.html是最好的事情(在我看来)。

了解Cookie

会话由response.sendRedirect("servlet2.html"); Cookie标识。如果浏览器转发此cookie,则会话转发到另一个servlet或控制器(或其他)。 JSESSIONIDHTTP是不同的协议,因此使用不同的Cookie。同样,HTTPs和IP地址是浏览器的不同主机,因此使用不同的cookie。如果localhostJSESSIONIDprotocol保持不变,则会转发host Cookie,但这与使用重定向中的相对路径具有相同的含义。重定向到相对地址可以被认为是在同一主机,协议和应用程序上下文上重定向的安全方式。 浏览器决定是否要转发您的webapp context Cookie

答案 1 :(得分:0)

这是它的工作方式,它首先检查相对重定向是否可用,然后构造绝对路径。

  // Generate a temporary redirect to the specified location
    try {
        String locationUri;
        // Relative redirects require HTTP/1.1
        if (getRequest().getCoyoteRequest().getSupportsRelativeRedirects() &&
                getContext().getUseRelativeRedirects()) {
            locationUri = location;
        } else {
            locationUri = toAbsolute(location);
        }
        setStatus(status);
        setHeader("Location", locationUri);
        if (getContext().getSendRedirectBody()) {
            PrintWriter writer = getWriter();
            writer.print(sm.getString("coyoteResponse.sendRedirect.note",
                    Escape.htmlElementContent(locationUri)));
            flushBuffer();
        }
    } catch (IllegalArgumentException e) {
        log.warn(sm.getString("response.sendRedirectFail", location), e);
        setStatus(SC_NOT_FOUND);
    }