Сервлет капчи вызывает java.lang.IllegalStateException: PWC3999: не удается создать сеанс после того, как ответ был зафиксирован - PullRequest
7 голосов
/ 13 января 2010

Я создаю вход CAPTCHA, используя SimpleCaptcha, и сделал проверку ввода 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

Как мне создать сеанс на моем сервлете? Как я могу решить эту проблему?

Большое спасибо.

Ответы [ 6 ]

16 голосов
/ 13 января 2010

Невозможно создать сеанс после подтверждения ответа

Сообщение об исключении довольно ясно. Есть средства незаконного государства. Вы не можете больше устанавливать / изменять заголовки ответа, когда ответ уже зафиксирован. Ответ фиксируется, когда заголовки уже отправлены на клиентскую сторону. Это точка нет возврата .

Ответ будет зафиксирован всякий раз, когда выходной поток был сброшен (в) напрямую. Это может произойти, когда вы записываете более 2 КБ в ответ (однако зависит от конфигурации сервера), или flush() выполняете вручную, или выполняете вызов sendRedirect().

Всякий раз, когда необходимо создать сеанс, сервер должен установить cookie в заголовке ответа, чтобы он мог идентифицировать конкретного клиента и связать его с экземпляром HttpSession в памяти сервера. Но это невозможно, если ответ уже зафиксирован, поэтому это исключение.

Обратно к основной причине этой проблемы:

Servlet.service () для исключения сервлета Captcha бросил

Это сервлет с servlet-name из Captcha, который вызвал эту проблему. Вам необходимо проверить / отладить всю цепочку запрос-ответ, чтобы увидеть, какие сервлеты / фильтры все вызываются и какие из них могли передать ответ до того, как сервлет Captcha смог создать сеанс. Я не могу помочь вам в дальнейшем, поскольку эта информация отсутствует в вашей теме.

По крайней мере, в приведенном ниже примере кода я вижу, что вы излишне вызываете response.getWriter(). Я не уверен, как выглядит код реального мира, может быть, вы удалили несколько строк, но есть вероятность, что вы действительно пишете в него, и это может быть основной причиной проблемы. Если вы напишите слишком много или сделаете флеш на нем, то восстановление будет зафиксировано. не пишите в ответ внутри сервлета, который должен быть контроллером. Там вы обычно используете JSP для. Или, если это для целей отладки, используйте стандартный вывод (System.out.println()) или Logger .

2 голосов
/ 01 июля 2011

Код ошибки в nl.captcha.servlet.SimpleCaptchaServlet Сервлете. Если вы измените его на StickyCaptcha, проблема исчезнет, ​​но, в частности, следующие строки в Servlet SimpleCaptcha.

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

На самом деле код записывает файл изображения в ответ (который обычно превышает значение по умолчанию 2k).

Так что на данный момент вы можете использовать StickyCaptcha или проверить код и решить проблему.

1 голос
/ 13 января 2010

Переместить эту строку:

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");

  //...
}

Это должно помочь.

0 голосов
/ 13 января 2010

Эта строка

 (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, или вы можете перевести ваш сервлет на один.

Есть ли примеры использования этой библиотеки catcha, которые вы могли бы изучить?

0 голосов
/ 13 января 2010

создать сессию, добавив это 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) { 
    ... 
} 
0 голосов
/ 13 января 2010

Похоже, что вы уже отправили заголовок клиенту перед обработкой сообщения. Если вы создаете сеанс, сервер должен отправить идентификатор сеанса клиенту. Обычно это делается путем отправки куки. Я полагаю, вы проверяете свой код на предмет того, выполняете ли вы обработку действия, прежде чем отправлять что-либо обратно клиенту.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...