Статьи

Еще немного о удушении внутри Tomcat

JSESSIONID

Два веб-приложения о предыдущей записи в блоге/a/ и /b/поддерживать свои собственные JSESSIONIDs, и были обновлены , чтобы показать его. Создайте и разверните приложение, как и раньше, и, используя Chrome, по очереди посетите эти два сайта : http: // localhost: 8080 / a / AFilterThatOutputsTheRequestsThreadID http: // localhost: 8080 / b / AServletThatOutputsTheRequestsThreadID

В Менеджере файлов cookie Chrome (Chrome prefs), вот cookie для «localhost», относящегося к /a/контексту, после нажатия на URL :

Обратите внимание, что поле «Путь» совпадает с именем веб-приложения.

Значение для / b / во многом совпадает, но отличается строковым значением JSESSIONID, которое вы наблюдали, когда посещали URL-адреса.

Если вы идете один дальше и перейти в один из URL — адресов , которые использует getServletDispatcher (..). Включают (..) , чтобы соединить два веб — приложения, то вы увидите только JSESSIONID для /a/использования для обоих.

Сервлеты Java в сравнении с правилами cookie браузера

Браузер не знает о серверных веб-приложениях Java; в частности, тот факт, что они хотят поддерживать разные JSESSIONID для каждого «контекста» ( /a/и /b/являются разными контекстами в контейнере сервлета). Браузер воспринимает их как каталоги и не делает того же различия, что контейнеры Java-сервлетов.

Теоретическая проблема

В браузере может быть один cookie-файл JSESSIONID, смонтированный в root ( /), который будет разрешен для взаимодействия браузера и веб-приложений «a» и «b» с сервером. Браузер подумает, что может отправить запрос, а Tomcat не узнает, что произошло.

Для нашего примера «a» и «b», как есть, с двумя файлами cookie, разделенными путями, теоретическая проблема остается именно такой.

Делая проблему реальной

Что если приложение /b/вместо этого было смонтировано в корневом контексте ( /)? Эффективно превращая «a» в подкаталог «b» в отношении браузера. Ну, у меня есть ветка Github, которая показывает только это:

git checkout b_is_now_root
mvn clean install
./copy_war_files.sh
cd apache-tomcat-7.0.41/bin
./catalina.sh run

Перво-наперво — удалите все куки для localhost в Chrome Cookie Manager.

Затем перейдите на страницу http: // localhost: 8080 / AServletThatOutputsTheRequestsThreadID (обратите внимание, что мы удалили/b/ часть URL-адреса ). Теперь у нас есть один cookie на localhost, и он сопоставлен с /(корневым) путем. Вы можете увидеть это в диспетчере файлов cookie.

Теперь давайте перейдем на http: // localhost: 8080 / a / AFilterThatOutputsTheRequestsThreadID для другого веб-приложения. На этот раз мы увидим это начальное взаимодействие с вкладкой сети инспектора Chrome:

Обратите внимание на корневой контекст JSESSIONID, идущий на сервер Tomcat, и второй JSESSIONID, сопоставленный с /a/возвращением.

Если для этого мы нажмем обновить в браузере, то оба будут отправлены в сервлет-контейнер с запросами, и это останется неизменным на протяжении всего жизненного цикла этого сеанса и контейнера сервлета:

В конце концов, контейнер сервлетов устраняет неоднозначность, так как он точно передает запросы в ‘a’ или root (бывший ‘b’).

Не только для удушения …

Конечно, это шире, чем стратегия задушить старое веб-приложение. Это влияет на любую ситуацию, в которой вы можете сделать несколько разумных хостингов для двух веб-приложений в одном домене из одного контейнера сервлета.

Желал для …

Было бы неплохо, чтобы механизм внутри context.xml Tomcat принудительно устанавливал один JSESSIONID для всех размещенных веб-приложений в одном домене. Примечание. Я не прошу, чтобы несколько приложений имели объединенные хранилища сессий внутри контекста сервлета (request.getSession () и т. Д.), Просто идентификаторы будут одинаковыми. В Servlet spec 3.x есть некоторые вещи, которые выглядят так, как будто вы можете переопределить значения пути по умолчанию для файлов cookie, но я не играл с этим.

Обновление: есть такой элемент конфигурации для context.xml Tomcat7: <Context ... sessionCookiePath="/" > ... </Context>