Сеанс теряется и создается как новый в каждом запросе сервлета

У меня есть большая проблема. Мой текущий сеанс пропадает каждый раз, когда я отправляю новый запрос на сервер.

Я проверил во многих местах. Я не могу найти в чем проблема. Я также включил session-config в web.xml как в tomcat, так и в приложении. Я также позволил принимать куки в моих браузерах. Проверено в каждом браузере. Это не работает.

Я просто разрабатываю простое приложение Java ee с использованием JSP/Servlet. Я столкнулся с проблемой только после того, как развернул на tomcat на сервере.

11 ответов

Решение

Спустя годы я так и не разместил ответ здесь. В то время я был занят и забыл об этом вопросе. Но сегодня я, как обычно, ищу решение в Stackru и вижу это уведомление, в котором говорится, что я получаю очки за этот вопрос. Похоже, что другие разработчики сталкиваются с той же проблемой. Итак, я попытался вспомнить, как я решил проблему. И да, я решил вручную вернуть идентификатор сессии, чтобы отслеживать / поддерживать идентификатор сессии.

Пожалуйста, посмотрите код, который я вручную положил обратно в jsessionid внутри сервлета.

HttpSession session = request.getSession();
if (request.getParameter("JSESSIONID") != null) {
    Cookie userCookie = new Cookie("JSESSIONID", request.getParameter("JSESSIONID"));
    response.addCookie(userCookie);
} else {
    String sessionId = session.getId();
    Cookie userCookie = new Cookie("JSESSIONID", sessionId);
    response.addCookie(userCookie);
}

Одной из возможных причин этого является наличие "обнаженного" имени хоста (т.е. без доменной части). Это довольно часто, если вы работаете в Интранете.

Проблема в том, что почти все файлы cookie браузера не принимают файлы cookie для имен хостов без имени домена. Это сделано для того, чтобы предотвратить evilsite.com от установки Cookie для com (что было бы плохо, так как это был бы конечный файл cookie для отслеживания).

Так что, если вы получите доступ к своему заявлению через http://examplehost/ он не будет принимать куки, в то время как для http://examplehost.localdomain/ он примет (и вернет) куки просто отлично.

Гадость в том, что сервер не может различить "браузер получил cookie и проигнорировал его" и "браузер так и не получил cookie". Таким образом, каждый отдельный доступ будет выглядеть как совершенно новый урок для сервера.

Сначала проверьте, если веб-приложение context.xml не имеет cookies="false" сконфигурировано.

Кроме того, полезно знать, что файлы cookie зависят от домена, порта и контекста. Если ссылки на странице указывают на другой домен, порт и / или контекстный путь в отличие от текущего URL-адреса запроса (который вы видите в адресной строке браузера), то файл cookie не будет пропущен, что приведет к тому, что сеанс больше не может быть идентифицирован, и, таким образом, вы получите новый от контейнера сервлетов.

Если это не причина, проверьте, не перенаправляете ли вы каждый запрос, используя HttpServletResponse.sendRedirect() по какой-то причине. Если вы сделаете это уже по самому первому запросу, то куки будут потеряны. Вам нужно будет заменить

response.sendRedirect(url);

от

response.sendRedirect(response.encodeRedirectURL(url));

В ваших свойствах

  server.session.cookie.http-only=true
  server.session.cookie.secure=true

Удалите эти настройки, он сохранит ваш cookie с идентификатором сессии, который сбрасывается при каждом запросе.

Из-за безопасного флага у меня возникла проблема с устаревшим файлом cookie сеанса https (мой специальный термин).

У меня была эта проблема при переключении между http и https. Файл cookie, сохраняемый сеансом https, никогда не перезаписывался сеансом http. Это осталось в памяти FireFox на вечность. Это было видно в FireFox Tools / Options / Privacy / Delete single cookie, где в поле Send for было только для безопасных соединений. Очистка этого файла cookie или всех файлов cookie - это обходной путь.

Я отлаживал проблему с помощью wget и заметил такой заголовок:

Set-Cookie: JSESSIONID=547ddffae0e5c0e2d1d3ef21906f; Path=/myapp; Secure; HttpOnly

Слово безопасное появляется только в соединениях https и создает этот устаревший файл cookie. Это SecureFlag (см. OWASP). Есть способы отключить этот флаг на стороне сервера, который кажется постоянным решением, но, возможно, небезопасным.

Или это ошибка браузера, что куки не перезаписываются?

Пожалуйста, проверьте, не является ли сеанс недействительным в вашем коде. Ищите код, похожий на request.getSession().invalidate();

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

Попробуйте добавить плагин Live Http Headers в firefox, убедитесь, что cookie-файл сеанса действительно передается в браузер с сервера, и убедитесь, что браузер отправляет его снова при следующем запросе.

Отредактируйте свой кот context.xml подать и заменить <Context> тег к <Context useHttpOnly="false">, это помогло мне.

Вы можете использовать @ResponseStatus(HttpStatus.NO_CONTENT) в методах вашего контроллера, например:

 @RequestMapping(value = "/{productId}", method = RequestMethod.DELETE)
 @ResponseStatus(HttpStatus.NO_CONTENT)
 public void delete(@PathVariable String productId)  {
     productDao.deleteById(productId);
    }

Вы подключаетесь через http или https? Для сервлетов сеанс, который я сохранял бы в файле cookie, имеет атрибуты «безопасный» и «httpOnly». «безопасный» означает, что пользовательский агент будет отправлять файлы cookie только в том случае, если транспорт защищен (https/tls). Если вы подключаетесь к http, новый сеанс создается при каждом запросе. «httpOnly» означает, что файл cookie не может быть изменен сценарием на стороне клиента.

Другие вопросы по тегам