7

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

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 上创建会话?我该如何解决这个问题?

非常感谢你。

4

6 回答 6

16

提交响应后无法创建会话

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

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

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

回到这个问题的根本原因:

Servlet Captcha 的 Servlet.service() 抛出异常

正是 servlet导致servlet-nameCaptcha这个问题。您需要检查/调试整个请求-响应链,以查看所有调用了哪些 servlet/过滤器,以及它们中的哪些可能在servlet 能够创建会话之前提交了响应。Captcha由于您的 topicstart 中缺少此信息,因此我无法为您提供更多帮助。

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

于 2010-01-13T11:42:26.593 回答
2

有问题的代码在nl.captcha.servlet.SimpleCaptchaServletServlet 中。如果您将其更改为StickyCaptcha问题将消失,但特别是以下是 SimpleCaptcha Servlet 中的违规行。

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

Actually the code is writing the image file to response (which is usually greater than default 2k).

So for the time being you can use the StickyCaptcha or checkout the code and fix the issue.

于 2011-07-01T09:35:11.490 回答
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");

  //...
}

这应该会有所帮助。

于 2010-01-13T09:33:36.470 回答
0

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

于 2010-01-13T09:22:19.800 回答
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) { 
    ... 
} 
于 2010-01-13T09:25:00.097 回答
0

这条线

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

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

例如,您可能有一个初始 serlvet

 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 库的使用示例?

于 2010-01-13T09:28:36.060 回答