Является ли мой метод страницы авто-перенаправления входа правильным в PHP? - PullRequest
2 голосов
/ 20 мая 2009

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

Мой метод - когда пользователь входит в систему, создает сеанс и обновляет таблицу пользователей в столбце состояния «онлайн». Если он нажмет кнопку выхода из системы, я установлю статус «офлайн». Что если он закроет свой браузер, не нажав кнопку выхода? Вот что я хочу сделать:

session_start();
if (!isset($_SESSION['LAST_ACTIVITY'])) {
    // initiate value
    $_SESSION['LAST_ACTIVITY'] = time();
}
if (time() - $_SESSION['LAST_ACTIVITY'] > 3600) {
    // last activity is more than 10 minutes ago
    session_destroy();
    //direct to a php, say this user is idle and thus status = offline
    header("location: update_status.php?user=".$_SESSION['username']."&status=offline");
    // den redirect them to login page
} else {
    // update last activity timestamp
    $_SESSION['LAST_ACTIVITY'] = time();
}

Это подходящий способ?


EDIT:

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

Нужно ли включать php?user=$_SESSION['userid'] в каждую ссылку?

Ответы [ 9 ]

5 голосов
/ 20 мая 2009

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

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

В запросе SQL, где вы храните свое время как datetime (это запрос для MySQL), это может выглядеть примерно так:

SELECT col1, col2, col3 FROM Users WHERE DATE_ADD(LastActive, INTERVAL 15 MINUTE) > NOW() AND UserIsFriendOfCurrentUser

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

4 голосов
/ 20 мая 2009

По моему мнению, это не сработает. Когда пользователь закрывает браузер, введенный здесь код никогда не будет вызываться.

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

Я думаю, что phpbb3 делает это таким образом ...

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

2 голосов
/ 20 мая 2009

После перенаправления местоположения заголовка обязательно поставьте эту строку:

die();

Не все пользовательские агенты (браузеры, веб-пауки и т. Д.) Будут прослушивать ваш заголовок перенаправления. Убить сценарий - это единственный безопасный способ убедиться, что они не получают остальную часть страницы.

0 голосов
/ 29 декабря 2011

Сеансы базы данных могут быть хорошим способом управления тем, кто в сети, а кто нет. Теоретически они должны истечь самостоятельно. Я написал в своем блоге с практическими рекомендациями об этом, вы можете прочитать больше на http://brennydoogles.wordpress.com/2011/09/06/taking-control-of-your-php-sessions-using-database-sessions/

Также имеется дополнительный бонус, позволяющий удаленно завершать сеанс пользователя, если вам необходимо:)

0 голосов
/ 21 мая 2009

Вы не должны использовать $_SESSION для хранения времени последней активности. Каждый раз, когда пользователь заходит на страницу, обновляйте столбец с именем last_activity, указав текущее время в таблице пользователей:

<?php
session_start();

$userId = (int)$_SESSION['user']; // make sure it's an integer
$db->exec('
    UPDATE users 
    SET last_activity = NOW() 
    WHERE id = ' . $_SESSION['id']
);
//...

Когда вы получаете список друзей, добавьте оператор if, чтобы проверить, находятся ли они в сети (это версия MySQL):

SELECT 
    u.user_name, u.name, etc,
    IF(
        UNIX_TIMESTAMP() - UNIX_TIMESTAMP(u.last_activity) < 300, 
        1, 0
    ) as online
    ... 

300 - это секунды, то есть 5 минут. Отрегулируйте это так, как считаете нужным. Тогда к вашим друзьям можно получить доступ так:

$friends = $db->query(/* above SQL */);
foreach($friends as $friend)
{
    if($friend['online'] == 1)
        // online specific stuff
    else
        // offline specific stuff
}
0 голосов
/ 20 мая 2009

В нашем проекте мы используем эту технику:

  1. каждый пользователь после входа в систему ассоциируется с идентификатором сессии.
  2. браузер отправляет «запрос активности» с AJAX по таймеру.
  3. облегченный серверный скрипт обновляет последнее действие в БД, выполняя поиск пользователь по идентификатору сеанса.
  4. cronjob обновляет всех тайм-аутов пользователей, помечая их как офлайн (фактически идентификатор сессии становится пустым), и выполняет процедуры выхода из системы для каждого пользователь, чтобы избежать повреждения данных на уровень бизнес-уровня.

Что происходит с пользователем? Пока пользователь не закроет свой браузер - активность обновляется. После закрытия браузера пользователь получает тайм-аут и помечается как отключенный. Когда пользователь пытается добраться до любого места, которое требует авторизации - первое, что мы пытаемся сделать, это найти его в БД по идентификатору сеанса, а если нет - он просто не может видеть ничего, кроме формы входа в систему (то есть include (); exit (); ).

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

0 голосов
/ 20 мая 2009

Лучший способ сделать это - сохранить время активности для зарегистрированных пользователей. Когда они переходят на страницу или выполняют действие, обновляют время своей «последней активности» в базе данных на текущее время. Если это время выходит за пределы порога (скажем, 15 минут), то вы можете классифицировать пользователя как неактивного.

0 голосов
/ 20 мая 2009

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

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

0 голосов
/ 20 мая 2009

Я вижу пару проблем в вашем коде:

if (time() - $_SESSION['LAST_ACTIVITY'] > 3600) {
  // last activity is more than 10 minutes ago
  session_destroy();
  //direct to a php, say this user is idle and thus status = offline
  header("location: update_status.php?user=".$_SESSION['username']."&status=offline");
}

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

Кстати, если я понимаю ваш вопрос, вы не получите предполагаемого поведения с этим кодом.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...