tomcat 7.0.59升级到7.0.61:响应提交后无法创建会话



我们正在从Tomcat 7.0.59升级到7.0.61,并得到以下错误。

此错误仅在通过Apache代理(无SSL)传递时发生。

当从浏览器调用Tomcat上下文时(没有Apache代理),它可以正常工作。

有人遇到过相同/类似的问题吗?

我们确实查看了变更日志(https://tomcat.apache.org/tomcat-7.0-doc/changelog.html),但我们没有找到任何解释Tomcat 7.0.61中此行为的更改

SEVERE: Servlet.service() for servlet [CaptchaServlet] in context with path [/cw] threw exception
java.lang.IllegalStateException: Cannot create a session after the response has been committed
    at org.apache.catalina.connector.Request.doGetSession(Request.java:3008)
    at org.apache.catalina.connector.Request.getSession(Request.java:2384)
    at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:897)
    at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:909)
    at be.servlet.CaptchaServlet.doGet(CaptchaServlet.java:127)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.filters.ExpiresFilter.doFilter(ExpiresFilter.java:1175)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
    at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:190)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

相关代码为:

    public void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
    HttpSession session = req.getSession();
    Captcha captcha = getNumberCaptcha(_width, _height, 5, Color.black);
    session.setAttribute(NAME, captcha);
    resp.setHeader("Cache-Control", "private,no-cache,no-store");
    resp.setContentType("image/png");

    // See https://wiki.apache.org/tomcat/FAQ/KnownIssues#ImageIOIssues
    // Wrap insite MyImageIOOutputStream
    ImageIO.write(captcha.getImage(), "png", new MyImageIOOutputStream(resp.getOutputStream()));
    resp.getOutputStream().flush();
    resp.getOutputStream().close();
}

在您开始说它是ImageIO之前,我们确实使用了https://wiki.apache.org/tomcat/FAQ/KnownIssues#ImageIOIssues.

中指定的MyImageIOOutputStream。

我们甚至尝试从File加载图像到字节数组并在响应中发送字节数组(因此没有使用ImageIO),但问题仍然是一样的。

令人惊讶的是,这个错误发生在Tomcat 7.0.61中,而不是在7.0.59中。该错误基本上表示您在发送HTTP响应的标头之后创建会话。这是一个问题,因为会话需要cookie,而cookie是在HTTP响应头中传输的。所以现在发送饼干已经太晚了。

假设CaptchaServlet是您的代码,最简单的解决方案是在servlet中写入任何输出之前创建会话(getSession())。那么使用任何servlet容器都是安全的。

我确认我有同样的问题比你(在我的特殊情况下,7.0.62 vs 7.0.59)。如果Tomcat版本是7.0.59,我的应用程序在apache代理后面工作得很好,但如果我在代理后面使用7.0.62,我有与你相同的跟踪。

我认为我们应该尽快向Tomcat报告

最新更新