Как предотвратить несколько логин на веб -сайте PHP

StackOverflow https://stackoverflow.com/questions/1727919

  •  19-09-2019
  •  | 
  •  

Вопрос

Я хочу предотвратить несколько логиков в приложении PHP.

Во -первых, я создаю состояние входа в систему (активное, уведомление) в пользовательской таблице.

Когда пользователь A журналы в статусе пользователя будут установлены для «активного», и если пользователь выходит из входа, статус установит «уведомление». Когда другой клиент пытается войти в систему, используя ту же Acount, я проверяю таблицу пользователя. Если пользователь все еще активен, вход ошибки будет отправлен пользователю.

Проблема возникла, если пользователь закрывает браузер, статус в пользовательском таблице может быть обновленным, поскольку пользователь не нажимал в систему.

У вас есть предложения по этому поводу?

Это было полезно?

Решение

(Обратите внимание, что хотя техника здесь все еще несколько действителен; образцы PHP не должны быть скопированы дословно, так как существуют более безопасные средства для включения значений, полученных пользователями в запрос SQL)


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

Я рекомендую вам сделать следующее;

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

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

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

Далее создайте функцию с названием authenticateUser() или аналогично, что будет вызвано в начале каждого сценария, чтобы убедиться, что пользователь аутентифицирован. Этот скрипт должен запросить базу данных, проверяя, имеет ли пользователь с идентификатором вашего пользователя хэш, который соответствует хэш вашего пользователя.

Например:

function authenticateUser($id, $hash, $databaseLink) {
    # SQL
    $sql = 'SELECT EXISTS(
               SELECT 1
               FROM `tbl_users`
               WHERE `id` = \''.mysql_real_escape_string($id).'\'
               AND `hash` = \''.mysql_real_escape_string($hash).'\'
               LIMIT 1
           );';

    # Run Query
    if ($query = mysql_query($sql, $databaseLink)) {
        # Get the first row of the results
        # Assuming 'id' is your primary key, there
        # should only ever be one row anyway.       
        $result = mysql_fetch_row($query);

        # Casting to boolean isn't strictly necessary here
        # its included to indicate the mysql result should
        # only ever been 1 or 0.
        return (bool)($result[0]);
    } else {
        # Query error :(
        return false;
    }
}

Затем мы просто передаем authenticateUser() пользователь ID, hash (по данным вашего сеанса) и database link (Для подключения к базе данных вы должны были открыть ранее).

Если authenticateUser() возврат true, пользователь аутентифицируется. Если false, пользователь не является или база данных недоступна или есть ошибка SQL.

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

Кроме того, ожидание истечения срока действия печенья - не лучший способ заставить людей, которые были неактивны, выходить из строя, поскольку вы никогда не должны доверять куки. Вместо этого вы можете добавить в столбец под названием last_active который вы можете обновлять каждый раз, когда пользователь аутентифицирует. Это также увеличит загрузку сервера, но позволит вам вручную переопределить несвежие журналы, удалив hash Для пользователей, которые, скажем, неактивны в течение 3 часов.

Другие советы

Вот решение, которое не требуется постоянная Доступ к базе данных работать...

(Что будет избежать требования проверять session_id () по значению базы данных каждый раз, когда вы запрашиваете/обновляете страницу, снятие напряжения DB/сервера) ...

1. При входе в систему возьмите ранее существовавшего session_id, хранящийся в БД для этого пользователя, и сделайте это:

session_id("the pre-existing session id in the database goes here");
session_start();
session_destroy();

2. Затем запустите новый сеанс и сохраните этот новый Session_ID в базе данных, перезаписывая предыдущий. Это будет выходить из предыдущего сеанса на этом пользователе, если есть один активный (эффективно вычеркнуть другого парня, используя эту учетную запись).

Попробуйте и дайте мне знать, если это поможет !!

Вы могли бы изменить свою модель, чтобы можно было войти только в последний пользователь.

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

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

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

Если вы не закончите с JavaScript, вы можете проверить, при входе в систему, если пользователь был активен в последние 15 минут. Если нет, вы можете войти в систему как новый пользователь.

Вы также можете сделать это с JavaScript. Сделайте Ajax Call, который стреляет каждую минуту или около того.

<script>
setInterval(function() {
  // do the ajax call
}, 60000);
</script>

Пусть этот вызов перейдет на сценарий, который отредактирует марку Lastonline в пользователе DB. При попытке входа в систему вы проверяете пользователь DB, если марка Lastonline превышает минуту, и у вас есть чек, если вы можете войти в систему. Это поможет, когда вы находитесь на странице, но вы не активны в последние 15 минут, и вы не хотите, чтобы кто -то другой входил в систему.

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

$unique_id = sha1('xzr4'.gethostbyaddr($_SERVER['REMOTE_ADDR']).$random_string.$_SERVER['HTTP_USER_AGENT'].'f8k2');

Если уникальный идентификатор не соответствует, вы просто выходите из пользователя.

Использование JavaScript на стороне клиента для отслеживания регистрации пользователя ненадежно.

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

При каждой попытке входа в систему, если сейчас ()-$ lastlogindate> predefined_timeout, вы должны принять новый вход, в противном случае отказаться от него.

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

Добавьте поле для SessionId в таблицу пользователя в базе данных.

Установите обработчик сеанса по умолчанию перед вызовом session_start () (необходимо для работы следующей строки кода):

session_set_save_handler(new \SessionHandler());

При каждом успешном входе в систему извлеките сохраненный $ SessionID из базы данных. Уничтожить старую сессию с:

(new \SessionHandler())->destroy($sessionID);

Получите новый идентификатор сеанса с:

$sessionID = session_id();

Храните новый идентификатор сеанса в базе данных.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top