Смешивание сессии - 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:

Итак, теперь мы работаем с этими настройками:

И мы планируем переключить 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.

Для получения дополнительной информации, смотрите это.

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