Предотвращение нескольких сеансов браузера на одном сеансе сервера - PullRequest
6 голосов
/ 01 февраля 2010

Я уверен, что мы все работали или знаем о веб-приложениях (особенно на предприятии), которые тесно связаны с сеансом сервера. В этих случаях возможно, что сеанс будет поврежден, если открыто более одного сеанса браузера и используется один и тот же файл cookie сеанса сервера. Мы рассмотрели все варианты и обнаружили, что наилучшим способом продвижения вперед будет препятствовать использованию нескольких сеансов браузера, которые совместно используют файл cookie сеанса сервера.

Это действительно проблема, только когда пользователь выполняет New Window - Ctrl+N в IE или эквивалент «дубликата табуляции» в других браузерах. По сути, мы получаем два активных сеанса браузера, которые используют одни и те же файлы cookie.

Итак, чтобы препятствовать этому (поскольку это, вероятно, будет непреднамеренным), я намеревался установить какую-то систему предупреждения для предотвращения такого поведения. Теперь наш код выполняет много проверок параллелизма, чтобы обеспечить целостность данных, но все еще могут быть проблемы с повреждением данных.

Мое решение после того, как я обнаружил, что общий ответ «невозможно», было положиться на AJAX для отправки «пингов» и измерения времени между ними. Итак, у нас есть общее правило: мы «пингуем» через определенный интервал, и если дельта между последним пингом в текущем пинге на меньше , чем длительность пинга, мы знаем, что у нас есть несколько активных сеансов браузера на один сеанс сервера.

Итак, где Pf - частота пинга; Pc - текущий пинг; и Pl - последний пинг, тогда мы имеем ошибку, когда Pf > (Pc - Pl).

           p1    p2    p3    p4
TAB1 0-----|-----|-----|-----|---...
                 :     :     :
                 :  p1 :  p2 :  p3    p4
TAB2          0-----|-----|-----|-----|---...
     ^     ^     ^  ^  ^  ^  ^  ^
                  Deltas
----+---+------------
TAB | P |   Delta (Pc - Pl)
----+---+------------                 
 1  | 1 |   5
 1  | 2 |   5
 2  | 1 |   2.5 -Error
 1  | 3 |   2.5 -Error
 2  | 2 |   2.5 -Error

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

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

В этом примере частота пинга установлена ​​на каждые 5 секунд. Если одновременно существует 100 пользователей, мы смотрим ~ 20 запросов в секунду для ping Servlet / HttpModule. Чтобы минимизировать ненужный сетевой трафик, я думал, что частота пинга будет уменьшаться со временем, пока не будет достигнут максимум 20 пингов в секунду. Это будет составлять ~ 5 запросов в секунду при 100 одновременных пользователях. Это компромисс, однако, поскольку это приведет к задержке обнаружения. Однако, как только обнаружение происходит, частота сбрасывается до 5 пингов / секунду до разрешения. (Эти цифры приведены только в качестве примера; они будут различаться в зависимости от среды)

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

Я пытаюсь определить, является ли это разумным подходом, если я нахожусь в мире боли. Любой опыт с проблемой будет полезен.

РЕДАКТИРОВАТЬ: Я знаю, что это звучит как лейкопластырь, но это должно быть мерой остановки, пока мы не сможем вырвать нарушающую библиотеку.

Ответы [ 7 ]

2 голосов
/ 21 сентября 2011

Какой браузер используют пользователи?
Мы решили решить проблему повреждения данных, когда вышел IE8, и предоставили опцию NoMerge.

2 голосов
/ 09 ноября 2011

Этого можно добиться с помощью JavaScript и файлов cookie, созданных на клиенте, в сочетании с тем фактом, что имя окна браузера / DOM должно быть уникальным. Очень прост в использовании без изменения вашего сайта.

1) При первой загрузке вашей страницы проверьте, существует ли ваш файл cookie сеанса, а если нет, то создайте файл cookie сеанса (не устанавливайте дату окончания срока действия) с уникальным именем и значением (какое-то кода). Задайте имя браузера / окна dom (НЕ заголовок) с этим значением cookie.

2) При последующих запросах вам необходимо убедиться, что имя окна DOM совпадает со значением cookie - если не перенаправить на страницу ошибки.

3) Не забудьте удалить файл cookie при выгрузке страницы, чтобы закрыть окно, чтобы удалить файл cookie.

Это работает, потому что если вы попытаетесь открыть дублирующееся окно, дублирующееся окно не будет иметь того же имени DOM окна, что и значение cookie - и вы можете ответить на этот факт.

Пример кода

function CheckMultipleSession() {
var existingCookieValue = getCookie("MySessionCookie");
if (existingCookieValue == null) { //first request so create cookie
   currentCookieValue = guid();
   setCookie("SessionGUID", currentCookieValue); 
   window.name = currentCookieValue; // setting DOM window name (this is key)
}
else {
if (existingCookieValue != window.name)
   top.location = "MultipleSessionsError.htm";                                       
}
}
2 голосов
/ 01 февраля 2010

Я работал над веб-приложением с одним окном много лет назад (до «Web 2.0»). Мы просто запустили новое окно без панелей инструментов (без кнопки «Назад» и т. Д.) И отключили щелчок правой кнопкой мыши. Мы позаботились о том, чтобы создать очень удобную сессионную навигационную систему. Этого было достаточно, чтобы предотвратить почти все случайные дубликаты просмотра. Это было интранет-приложение; очевидно, я бы никогда не рекомендовал делать что-либо подобное на общем веб-сайте.

Лично мне не нравится звук пинг-детектора. Я бы просто позаботился о том, чтобы повреждение данных никогда не происходило. Несколько сессий браузера не является оправданием для этого ... хотя я понимаю, как это может быть проблематично. Но если вы хотите добавить пинг-детектор поверх отлично работающего кода, это может послужить полезным напоминанием пользователю.

Вы можете добавить уникальный токен в конец каждой ссылки. Если уникальный токен используется более одного раза (например, открытие нового окна, закладка, назад, вперед), тогда запрос может быть отклонен. При правильном отслеживании вы можете убедиться, что невозможно перейти с одной страницы на другую, не выбрав правильный путь. Этот подход более надежен, чем пинг (так как он контролируется сервером), но может привести к очень раздражающему взаимодействию с пользователем.

Суть в том, чтобы исправить ваше приложение, чтобы не повредить данные. Я знаю, что это не может быть тривиальной вещью, и я не хочу пролить свет на это. Внедрение эхо-запросов и тому подобного может помочь устранить проблему, но я гарантирую, что если что-то пойдет не так, это в конечном итоге будет. : -)

1 голос
/ 11 августа 2011

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

1 голос
/ 01 февраля 2010

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

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

Я бы немного изменил ваш подход, и в пинг-сообщении содержалась бы дата / время клиента, чтобы вы вообще могли избежать задержки в сети в своих вычислениях.

1 голос
/ 01 февраля 2010

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

0 голосов
/ 01 февраля 2010

Очень простое решение, которое вы можете или не можете использовать, состоит в том, чтобы иметь одну страницу (т. Е. Один URL, например home.whither) для приложения ajax. Если они запрашивают ту же страницу во второй раз и уже существует действительный сеанс, то вы знаете, что они открыли новую вкладку или новое окно. Обратите внимание, что вы не сможете отличить это от обновления, однако.

Ваше решение слишком сложное.

...