JSESSIONID столкновение между двумя серверами на одном и том же IP-адресе, но с разными портами
У меня есть ситуация, когда у меня есть два разных webapps, работающих на одном сервере, используя разные порты. Они оба запускают контейнер сервлетов Java Jetty, поэтому оба они используют параметр cookie с именем JSESSIONID для отслеживания идентификатора сеанса. Эти два webapps сражаются за идентификатор сеанса.
- Откройте вкладку Firefox и перейдите в WebApp1
- HTTP-ответ WebApp1 имеет заголовок set-cookie с JSESSIONID = 1
- В Firefox теперь есть заголовок Cookie с JSESSIONID = 1 во всех его HTTP-запросах к WebApp1
- Откройте вторую вкладку Firefox и перейдите в WebApp2
- HTTP reqeust для WebApp2 также имеет заголовок Cookie с JSESSIONID = 1, но в doGet, когда я вызываю
req.getSession(false);
, я получаю null
. И если я вызываю req.getSession(true)
, я получаю новый объект Session, но тогда ответ HTTP от WebApp2 имеет заголовок set-cookie с JSESSIONID = 20
- Теперь у WebApp2 есть рабочий сеанс, но сеанс WebApp1 отсутствует. Переход к WebApp1 даст мне новый сеанс, сдувающий сеанс WebApp2.
- Продолжить навсегда
Итак, сеансы разбиваются между каждым веб-приложением. Мне бы очень хотелось, чтобы req.getSession(false)
вернул действительный сеанс, если уже определен файл cookie JSESSIONID.
Один из вариантов заключается в том, чтобы в принципе переопределить структуру сеанса с помощью HashMap и файлов cookie, называемых WEBAPP1SESSIONID и WEBAPP2SESSIONID, но это отстойно, и это означает, что мне придется взломать новый материал Session в ActionServlet и несколько других мест.
Это должна быть проблема, с которой столкнулись другие. Является ли Jetty HttpServletRequest.getSession(boolean)
просто crappy?
Ответы
Ответ 1
У меня была аналогичная проблема: один или несколько экземпляров одного и того же приложения на localhost на разных портах, выбранных во время запуска приложения, каждый из которых использует свой собственный экземпляр причала.
Через некоторое время я придумал следующее:
- Подождите, пока инициализируется причал
- использовать причал SocketManager для получения порта (
socketManager.getLocalPort()
)
- установить имя файла cookie через SessionManager
(sessionHandler.getSessionManager().setSessionCookie(String)
)
Таким образом, у меня есть имя cookie разницы для каждого экземпляра - таким образом, больше никаких помех.
Ответ 2
Это не проблема Jetty, это то, как была определена спецификация cookie. Помимо пары имя/значение, файл cookie может также содержать дату истечения срока действия, путь, имя домена и безопасный файл cookie (т.е. Предназначенный только для SSL-соединений). Номер порта не указан в приведенном выше;-), поэтому вам нужно будет изменить либо путь, либо домен, как говорит stepancheg в своем ответе.
Ответ 3
В нашем случае мы используем Tomcat, поэтому решение должно использовать разные имена cookie сеанса для каждого экземпляра.
В context.xml
сделайте что-нибудь вроде
<Context sessionCookieName="JSessionId_8080">
Ответ 4
Я копаю, и я обнаружил, что в AbstractSessionManager
существует метод под названием getCrossContextSessionIDs()
. Если он возвращает true
, то при создании нового сеанса Jetty сначала проверит, установлен ли JSESSIONID, и попытайтесь использовать этот существующий идентификатор сеанса. Я думаю, что я могу установить значения true
, используя какое-то свойство java при запуске.
При дальнейшем копании это только поможет мне, если я запустил два webapps в разных контекстах одного и того же Jetty (следовательно, кросс-контекст). При создании нового объекта Session
выбирается новое значение JSESSIONID
. Если getCrossContextSessionIDs()
возвращает true
, то он проверяет, было ли текущее значение JSESSIONID
создано этим Jetty (включая все остальные контексты), и если оно было, оно будет повторно использовать его.
Поскольку я имею дело с двумя разными экземплярами Jetty, запущенными на двух разных портах, мне нужно взломать источник Jetty, чтобы не выполнять эту проверку, или просто создать собственную среду, подобную сеансу.
Ответ 5
Это правильное поведение. Вы можете разместить два своих веб-клиента в разных доменах или разными путями.
Ответ 6
Вы также можете установить путь jsessionid cookie, я полагаю.