Подтвердить что ты не робот

На сайте asp.net как предотвратить множественные логины одного и того же идентификатора пользователя?

Просьба указать, как предотвратить одновременное вход в систему нескольких пользователей с использованием идентификатора пользователя?

Я искал в Интернете и нашел некоторые способы, но почему-то они не работают в таких ситуациях:

  • Если javascript в браузере отключен.
  • Если пользователь не нажимает выйти и напрямую закрывает браузер.

Пожалуйста, предложите мне какой-то способ.

спасибо

haansi

4b9b3361

Ответ 1

Там может быть несколько возможностей. Быстрый ответ:

  • Поддерживать флаг в базе данных; при каждом обновлении флажка. Например, при каждом запросе проверки подлинности вы можете отклонить запрос на вход, если флаг уже прав.

  • Кроме того, вы можете сохранить список пользователей в объекте Application и использовать .Contains, чтобы узнать, существует ли он.

- EDIT -

Давайте попробуем параметр флага базы данных; и предположим, что у вас есть метод под названием StillLoggedIn(User), который обновляет дату/время и флаг.

Итак, когда пользователь входит в систему:

  • Приложение будет аутентифицировать пользователя и установить флаг = 1 и пометить отметку даты/времени.
  • Для последующих запросов приложение вызывает StillLoggedIn(User);

  • Подготовьте службу Windows, которая время от времени будет просматривать базу данных (скажем, через 5 минут, если у вас есть 10000 пользователей). Служба будет сравнивать дату/время базы данных с текущей датой/временем и пометить флаг как 0, если currentTime минус lastUsedTime больше, скажем, 5 минут.

Это может быть что угодно, кроме базы данных и службы Windows.

Ответ 2

Мы реализовали систему для этого в следующих строках:

  • Добавлено свойство профиля пользователей для хранения идентификатора сеанса.
  • Всякий раз, когда пользователь входит в систему, сохраните свой идентификатор сеанса в профиле.
  • На любой странице, требующей такого уровня безопасности, проверьте, соответствует ли идентификатор сеанса, сохраненный в профиле, их сеансу. Эта проверка может быть выполнена в пользовательском обработчике событий AuthorizeRequest или может выполняться в базовом классе, из которого эти страницы происходят, а если нет, перенаправлять их на страницу входа.

Мы пошли для опции базового класса, поскольку у нас есть два уровня аутентификации:

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

Основные проблемы, которые вы найдете практически в любой системе:

  • Использование IP-адреса пользователей является ненадежным - корпоративные пользователи, те, кто находится за прокси-серверами, и т.д., часто используют IP-адрес, поэтому он будет отображаться как один и тот же пользователь.
  • Полагая, что пользователь выходит из системы, ненадежен - компьютер/браузер пользователей может потерпеть крах, не предоставив им возможность выйти из системы, пользователь может/забудет выйти из системы.
  • Опора на тайм-ауты сеанса ненадежна - если вы не используете сеансы InProc, событие SessionEnd никогда не срабатывает, если ваш сервер выходит из строя, событие не вызывается и т.д.

Проблемы, которые вы найдете с таким решением, как мои:

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

Ответ на комментарий

В ответ на ваши конкретные запросы:

  • поставщик профилей по умолчанию сохраняет данные в той же базе данных SQL, что и поставщик членства (таблицы создаются вместе с членством и ролями таблицы). Если вы должны были хранить его "в кеше", это должен быть глобальный кэш приложений по строкам KMan предлагает в варианте 2 - и, как указано в комментариях, вам нужно будет построить тайм-аут для этого, и это вернет к вопросу о достоверном определении этого.
  • Пользователь не выходит из системы: он обрабатывается в нашей системе, не блокируя будущих пользователей, а блокируя ранее зарегистрированных пользователей - так:
    • Алиса приходит на сайт, входит в систему, начинает просмотр.
    • Боб приходит на сайт и входит в систему с деталями Алисы, начинает просмотр.
    • Алиса пытается продолжить просмотр, заблокирована, ей нужно снова войти в систему.
    • Боб теперь заблокирован.
    • и др.

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

Ответ 3

Здесь нет ни одного ответа, поскольку это зависит от того, как вы аутентифицируете пользователей. Однако основная логика была бы простой: когда пользователь входит в систему, проверяет свое имя пользователя или идентификатор на список уже зарегистрированных пользователей и, если есть совпадение, не аутентифицирует их (и вместо этого дает им какое-то сообщение, объясняющее почему они не могут войти в систему).

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

Ответ 4

Я просмотрел таблицу членства и не видел ни одного столбца, такого как "IsLoggedIn", поэтому членский API не отвечает этому требованию.

Возможно, вы можете использовать систему кэша Asp.net и указать пользователя как "LoggedIn". Таким образом, вы можете проверить дополнительные логины.

Ответ 5

Так я и делаю.

После входа в систему, проверьте флаг и идентификатор сеанса от БД, если вы вошли в систему с той же учетной записью и другим идентификатором sessionID (Сравните недавно сгенерированный текущий идентификатор сеанса и идентификатор сеанса от БД), предупредите пользователя о том, что "система обнаружила, что вы не вышли из системы ваш последний логин, нажмите <" OK " > , чтобы выйти из последнего входа и создать новый сеанс." Если ОК, просто замените старый SessionId текущим SessionID в DB.

Еще одна вещь - проверить текущие идентификаторы sessionID и sessionID из БД на каждой странице, если это не так, выйти и перенаправить на страницу входа.

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

Надеюсь на эту помощь, спасибо...

Ответ 6

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

Когда пользователь регистрирует свой userId, он извлекается из базы данных членства asp.net и сохраняется в состоянии приложения как уникальный объект.

Так как состояние приложения является глобальным для приложения и не является специфичным для пользовательского сеанса, мы можем проверить, сохранен ли userId в состоянии приложения. Если он уже сохранен, мы можем уведомить пользователя и остановить вход в систему. Когда сеанс истекает (в Session_End в файле Global.asax), этот объект состояния приложения для этого конкретного пользователя может быть удален из состояния приложения, чтобы он мог снова войти в систему после истечения срока его сессии.

Здесь код: В Login.aspx.cs:

protected void OnLoggingIn(object sender, LoginCancelEventArgs e)
    {
        // Accesses the database to get the logged-in user.
        MembershipUser userInfo = Membership.GetUser(LoginUser.UserName);
        UserMan.UserID = userInfo.ProviderUserKey.ToString();

        if (Application[UserMan.UserID] != null)
        {
            if (Convert.ToString(Application[UserMan.UserID]) == UserMan.UserID)
            {
                e.Cancel = true;
            }
            else
            {
                // Save the user id retrieved from membership database to application state.
                Application[UserMan.UserID] = UserMan.UserID;
            }
        }
        else
        {
            Application[UserMan.UserID] = UserMan.UserID;                
        }
    }

И в Global.asax:

void Session_End(object sender, EventArgs e)
    {
        // Code that runs when a session ends. 
        // Note: The Session_End event is raised only when the sessionstate mode
        // is set to InProc in the Web.config file. If session mode is set to StateServer 
        // or SQLServer, the event is not raised.

        if (Application[UserMan.UserID] != null)
        {
            if (Convert.ToString(Application[UserMan.UserID]) == UserMan.UserID)
            {                    
                Application.Contents.Remove(UserMan.UserID);
            }
        }
    }

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

Ответ 7

Zhaph - Ben Duguid, Небольшой заметки Профиль не может быть доступен в AuthenticateRequest, поскольку он не создан до события приложения AcquireSessionState, поэтому, если бы они использовали такой подход (вместо подхода к странице), им пришлось бы обрабатывать AcquireRequestState или PostAcquireRequestState

Ответ 8

Когда член входа в систему. setup a Random int ex. randNo, сохранить кеш [UserName] = randNo, session [UserName] = randNo. Когда участник получает доступ к любой странице, мы проверяем: cache [UserName] == Session [UserName] в порядке, иначе этот пользователь будет выходить из системы. (Среднее: сначала вход, выход из системы)