Captcha servlet导致java.lang.IllegalStateException:PWC3999:响应提交后无法创建会话

时间:2010-01-13 09:07:46

标签: session servlets glassfish captcha simplecaptcha

我正在使用SimpleCaptcha创建一个CAPTCHA输入,并对Captcha输入进行了验证。我使用以下代码创建了验证码输入。

HTML代码:

<form action="submit_proceed.do" method="post">
<img src="captchaImg" /><input type="text" name="captcha" value=""><br />
<input type="submit" value="Submit" name="submit" />
</form>

JavaServlet代码:

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Iterator;
import nl.captcha.Captcha;

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();

List errorMsgs = new LinkedList();
try{
    // Validate Captcha
    HttpSession session = request.getSession(true);
    String userCaptcha = request.getParameter("captcha");
    Captcha captcha = (Captcha) session.getAttribute(Captcha.NAME);
    if (!captcha.isCorrect(userCaptcha)) {
        errorMsgs.add("Please input the correct Captcha value.");
    }
} catch (RuntimeException e) {
    errorMsgs.add("An unexpected error: " + e.getMessage());
    RequestDispatcher view = request.getRequestDispatcher("/error.view");
    view.forward(request, response);
}

但是我一直收到这个错误:

StandardWrapperValve[Captcha]: PWC1406: Servlet.service() for servlet Captcha threw exception
java.lang.IllegalStateException: PWC3999: Cannot create a session after the response has been committed

如何在servlet上创建会话?我该如何解决这个问题?

非常感谢。

6 个答案:

答案 0 :(得分:16)

  

在提交响应后无法创建会话

异常消息非常清楚。有非法国家的手段。当响应已经提交时,您不能再设置/更改响应头。当标头已经发送到客户端时,将提交响应。这是不归的要点。

只要直接刷新(输入)输出流,就会提交响应。当您为响应写入超过2K(但取决于服务器配置),或手动flush()或进行sendRedirect()调用时,可能会发生这种情况。

每当需要创建会话时,服务器需要在响应头中设置cookie,以便它可以识别特定客户端并将其与服务器内存中的HttpSession实例相关联。但如果响应已经提交,那就不可能,因此这个例外。

回到此问题的根本原因:

  

Servlet.service()for servlet Captcha抛出异常

servlet-name Captcha导致此问题的servlet。您需要检查/调试整个请求 - 响应链,以查看哪些servlet /过滤器都被调用,以及哪些servlet /过滤器可能已经提交了响应,之后 Captcha servlet能够创建会话。我无法帮助您,因为您的主题启动中缺少此信息。

至少,在目前给定的代码示例中,我发现您不必要地调用response.getWriter()。我不确定真实世界的代码是什么样的,也许你已经删除了一些代码,但是你实际上可能正在写它并且这可能是问题的根本原因。如果你写得太多或者对它进行了刷新,那么将会提交resopnse。 写入应该是控制器的Servlet内的响应。你通常在那里使用JSP。或者,如果是出于调试目的,请使用标准输出(System.out.println())或Logger

答案 1 :(得分:2)

违规代码位于nl.captcha.servlet.SimpleCaptchaServlet Servlet中。如果将其更改为StickyCaptcha,问题将会消失,但具体而言,以下是SimpleCaptcha Servlet中的违规行。

CaptchaServletUtil.writeImage(resp, captcha.getImage());
req.getSession().setAttribute(NAME, captcha);

实际上代码是将图像文件写入响应(通常大于默认值2k)。

因此暂时您可以使用StickyCaptcha或签出代码并解决问题。

答案 2 :(得分:1)

移动此行:

HttpSession session = request.getSession(true);

是doPost方法中的第一个语句。

protected void doPost(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {

  HttpSession session = request.getSession(true);

  response.setContentType("text/html;charset=UTF-8");

  //...
}

这应该有所帮助。

答案 3 :(得分:0)

似乎您在处理帖子之前已将标题发送给客户端。如果创建会话,则服务器需要将会话ID发送到客户端。这通常通过发送cookie来完成。我想你检查代码是否在将任何内容发送回客户端之前执行了操作处理。

答案 4 :(得分:0)

通过添加此创建会话 javax.servlet.http.HttpSession session = request.getSession();


try{ 
 javax.servlet.http.HttpSession session = request.getSession();
    // Validate Captcha 
    String userCaptcha = request.getParameter("captcha"); 
    Captcha captcha = (Captcha) session.getAttribute(Captcha.NAME); 
    if (!captcha.isCorrect(userCaptcha)) { 
        errorMsgs.add("Please input the correct Captcha value."); 
    } 
} catch (RuntimeException e) { 
    ... 
} 

答案 5 :(得分:0)

这一行

 (Captcha) session.getAttribute(Captcha.NAME);

暗示在处理此特定请求之前会话应该已经存在,因此我想知道在发送原始表单之前是否应该进行一些初始化。这应该由您正在使用的框架指定。

例如,你可能有一个初始的血清

 creates the image, figures out the value of Capcha.Name
 creates the session 
 session.setAttribute(Capcha.NAME, theName)
 emit the html (or forward() to a JSP)

你可以在JSP中完成所有操作,或者你可以将你的servlet转发给一个。

您可以检查一下这个catcha库的使用示例吗?