Смешивание сессии - apache httpd с mod_jk, tomcat, spring security - обслуживание данных другого пользователя
Недавно мы столкнулись с серьезной проблемой, что один пользователь обслуживал данные другого пользователя. Эту проблему практически невозможно воспроизвести.
Мы используем стандартное управление зарегистрированными пользователями, предоставляемое Spring-security, и мы уверены, что проблема не в том, чтобы хранить пользователя в переменной экземпляра или аналогичную параллельную среду в нашем приложении.
Мы действительно сомневаемся, что проблема в SpringSecurity или в самом Tomcat.
Наш фронт-сервер - это apache httpd, подключенный к tomcat через коннектор ajp (mod_jk). Мы не занимаемся балансировкой нагрузки (httpd заботится только о SSL, переписывает некоторые URL и обслуживает некоторые модули php)
Вот наша установка:
## OS
OS Name: Linux
OS Version: 2.6.32-5-686
Architecture: i386
## Apache httpd
Server version: Apache/2.2.16 (Debian)
Server built: Sep 4 2011 20:27:42
## mod_jk
mod_jk/1.2.30 (installed via apt-get)
## JVM
JVM Version: 1.6.0_18-b18
JVM Vendor: Sun Microsystems Inc.
## Tomcat
Server version: Apache Tomcat/6.0.28
Server built: February 12 2011 1443
Мы обвиняем httpd / mod_jk в этом смешивании сеанса, поэтому наше единственное решение - удалить apache httpd. Но прежде чем мы оставим эту популярную и широко используемую конфигурацию, мы бы хотели узнать, сталкивался ли кто-либо с подобной проблемой.
Единственные похожие проблемы, которые я обнаружил, были в балансировке нагрузки или mod_jk.
Сталкивались ли вы когда-нибудь с подобной проблемой? Любые советы, идеи, ссылки или опыт будут высоко оценены. Спасибо!
5 ответов
Одной из возможных проблем может быть вторая попытка входа в систему. Рассмотрим следующий случай:
- Пользователь открывает две вкладки браузера с двумя формами входа.
- Вкладка 1: войдите как user_1. Загрузите некоторые данные в сеанс HTTP.
- Вкладка 2: войдите как user_2. Загрузите некоторые данные в сеанс HTTP.
В большинстве браузеров это будет один и тот же сеанс HTTP. Так что на самом деле вы будете иметь данные от user_1 и user_2, объединенные в одном сеансе HTTP. Это может повлиять на любую страницу, которая использует объекты сеанса.
У вас есть два варианта здесь:
- Предотвратите эту ситуацию. Определите вторую попытку входа и попросите пользователя сначала выйти из системы. С Spring Security это легко, см. Код ниже.
- Если вам абсолютно необходима одна учетная запись для каждой вкладки браузера, вы можете сохранить данные сеанса на карте для каждого имени пользователя.
Вы можете предотвратить вторую попытку входа в систему благодаря функции Concurrent Session Control:
<http>
...
<session-management>
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</session-management>
</http>
Это уже сделано в вашем приложении?
Если вы исключите проблему одновременного сеанса, то практически единственная возможность состоит в том, что ваша бизнес-логика сама по себе имеет недостатки и обслуживает данные другого пользователя. Пожалуйста, опубликуйте примеры кода, как определяется "текущий пользователь" и используется позже.
РЕДАКТИРОВАТЬ: ошибки, которые проявляются только в производстве, часто вызваны условиями гонки ( http://en.wikipedia.org/wiki/Race_condition). Убедитесь, что ваш код использует локальные переменные, когда это возможно, и используйте блокировку / синхронизацию, где это применимо.
Пока что нам не удалось воспроизвести ошибку, но мы обнаружили, что некоторые люди сталкивались с той же проблемой с mod_jk:
- https://issues.apache.org/bugzilla/show_bug.cgi?id=47714
- http://grails.1312388.n4.nabble.com/Spring-Security-after-log-in-user-changed-and-session-mixed-up-td4636714.html (внизу)
Итак, теперь мы работаем с этими настройками:
- JkOptions DisableReuse: http://tomcat.apache.org/connectors-doc/webserver_howto/apache.html
- работник повторяет попытки = 0: http://tomcat.apache.org/connectors-doc/reference/workers.html Worker Directives
И мы планируем переключить mod_jk для mod_proxy_http.
Я оставляю этот вопрос без ответа, потому что я не могу заверить (и никто не сталкивался с такой же проблемой, чтобы убедиться), что решение исправляет ошибку.
Если бы кто-то мог поделиться какой-либо информацией, я был бы очень признателен! Благодарю.
Я столкнулся с той же проблемой с Glassfish 3.1.2.2 и Mod_JK 1.2.19
Вы можете воспроизвести ошибку с помощью скрипта JMeter и хорошего утверждения.
Вот мой пост в блоге, рассказывающий историю: http://jeecookbook.blogspot.com/2013/07/modjk-session-mixed-between-users.html
Использование Mod_proxy с этим утверждением решит проблему: микширование больше не обнаружено.
Когда вы интегрируете JSF и Spring, внедрение зависимостей JSF вступает в конфликт с внедрением зависимостей Spring, поэтому Spring переписал модуль JSF, который обрабатывает это, чтобы вместо этого просто обернуть Spring DI. Поэтому, когда я объявляю JSF ManagedBean как Session Scoped, я также должен дать ему @Controller
аннотации, чтобы он также распознавался как Spring Bean.