И снова авторизация или ФАНАТ откликнись

krafty

new Exception
И снова авторизация или ФАНАТ откликнись

Вернемся к нашим баранам.
Логика такая.
в index.php вводим логин и пароль.
в auth.php удаляем из таблицы users_online (поля: id|login|online_since|sid) записи, у которых online_since меньше на более чем 3 часа по сравнению с текущим временем.
далее сравниваем с БД логин и пароль, стартуем сессию. если авторизовался, то смотрим в ussers_online есть ли там такой логин. если есть, то дальше не пропускаем. если нет, то отправляем на admin.php, где проверяем существование сессионной переменой и равенство sid текущей сессии и sid из таблицы users_online.

Теперь рассказываю в чем загвоздка.
Допустим юзер успешно авторизовался. скрипт прописал его в users_online, пропустил на admin.php. он (юзер) поработал 2 часа и ...закрыл браузер. сессия уничтожилась. в таблице users_online осталась запись. через 20 мин ему снова захотелось зайти. открывает index.php, авторизуется, но auth.php его не пропускает, т.к. существует в таблице userd_online запись с его логином. эта запись при старте скрипта не удалилась (не прошло 3 часа). вобщем никуда он не попадает, хотя имеет на это полное право.
Че делать? отказываться от использования дополнительной таблицы не хочется, т.к. она не дает возможности зайти в одно время в систему с одинаковыми логинами.
может проверять в auth.php при старте есть ли в базе логин у которого не истекло время и если совпадает с авторизовавшимся, то переписать sid пропускать дальше. не повлияет ли это на безпасность системы. надо подумать...
ЗЫ. если нужны исходники, могу запостить
 

SiMM

Новичок
> в таблице users_online осталась запись. через 20 мин ему снова захотелось зайти.
Ну и что? Наличие записи в таблице не запрещает проходить авторизацию. Да и SID-то у человека уже другой.
 

krafty

new Exception
авторизацию он пройдет, но скрипт auth.php не пропустит дальше. там условие: если такой логин есть в таблице users_online, то дальше не пускаем. если б как-то удалять запись, когда пользователь закрывает браузер. или чистить таблицу не только по времени, а и по sid'у, т.е. смотрим время не прошло (менее 3 часов), далее смотрим, если sid другой (не такой как в таблице), то удаляем запись - она осталась от прошлого сеанса. короче сейчас буду пробывать.
 

SiMM

Новичок
> там условие: если такой логин есть в таблице users_online, то дальше не пускаем.
Так убери условие.

> т.е. смотрим время не прошло (менее 3 часов)
Зачем там столь длительное время?
 

krafty

new Exception
Условие исключает вход в систему разных юзеров под одним именем - убрать нельзя (заменить можно). Время пока взял с потолка

-~{}~ 13.08.05 14:01:

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

-~{}~ 13.08.05 14:04:

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

tashkentchi

Новичок
А если "неправильный" юзер в онлайне, то "правильный" тоже ждать должен?

-~{}~ 13.08.05 17:38:

А если админ хочет в 5 окошках работать, то тоже пусть обломится?
 

krafty

new Exception
может вообще не стоит запрещать доступ нескольким пользователям по одному логину?
 

tashkentchi

Новичок
Точно. Если админ посеял свой пароль, то он сам себе злой Буратина и вышеописанными средствами ему не поможешь. А если админский пароль знает только админ, то эти средства вообще не нужны, только мешать будут.
 

krafty

new Exception
теперь все выглядит так. смотрим в users_online. если нет такого логина - добавляем, если есть, то просто UPDATE полям sid и online_since.
думаешь не стоит пререстраховываться на тот случай, если админский пароль знает еще кто-то? в этом случае два чела будут на сайте, а запись в таблице будет одна. вот те и неразбериха с sid. тот кто зашел первый без задней мысли занимается администрированием. тут заваливается второй - происходит UPDATE, т.е. изменяется sid в БД. первый после этого переходит по какой-нить ссылке на скрипт. энтот скрипт как обычно запрашивает из users_online sid и сравнивает с текущим, а они-то не равны. как-то несправедливо получается. преимущество имеет второй зашедший!
 

tashkentchi

Новичок
А зачем тебе нужна users_online? Пусть все происходит так:
В index.php вводим логин и пароль. Далее сравниваем с БД логин и пароль, стартуем сессию. Сохраняем логин в сессии. Отправляем на admin.php, где проверяем существование сессионной переменой логин и права доступа соответствующего юзера.
 

krafty

new Exception
только перед стартом сессии в admin.php нужно сделать unset($logged_user), чтоб никто не смог передать через урл какое-нибудь значение. не пойму какое практическое значение имеют идентификаторы сессии. для самого php они ясное дело нужны. а для меня? и мне кажется, что так защита более уязвима.
ксати, в книге Д.Котерова "PHP 5" в главе про сессии, где описывается автоматическое добавление sid к урл (или в куки) написано "...зачем же тогда нужен sid? Да низачем!...".
не знаю кому верить. мой начальник настаивает на использовании этой таблицы. прийдется ему пояснить, какие сложности возникает при такой логике авторизации. по-моему их уже стало больше, чем выгоды от этого всего.
 

tashkentchi

Новичок
мой начальник настаивает на использовании этой таблицы. прийдется ему пояснить, ...
Не надо ничего пояснять. Хочет - пусть будет. Лишь бы не мешала :)
перед стартом сессии в admin.php нужно сделать unset($logged_user), чтоб никто не смог передать через урл какое-нибудь значение.
Пользуйся массивом $_SESSION
 

krafty

new Exception
Автор оригинала: tashkentchi
Пользуйся массивом $_SESSION
типа такого:

PHP:
if (!isset($_SESSION['logged_user']))
{
  echo "Доступ запрещен!";
  require './index.php';
  die;
}
ОК! сохраняю старые версии в резервный каталог на всякий случай (я насчет начальника) и забываю пока про эту таблицу. Как я понял, так редко (если вообще никогда) делают
 

Фанат

oncle terrible
Команда форума
можно писать в юзерс онлайн айпишник
и пускать с того же

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

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

-~{}~ 13.08.05 17:10:

Как я понял, так редко (если вообще никогда) делают
если тебе надо отсекать параллельное использование (например у тебя порносайт), то без неё не обойтись.

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

krafty

new Exception
Автор оригинала: Фанат
можно писать в юзерс онлайн СИД, и проверять при каждом просмотре страницы, совпадает ли сид с логином.
тогда два параллельных будут постоянно дроуг друга выкидывать.
я не понял как это применять. проверяем при успешной авторизации юзерс онлайн. если есть такая запись, то удаляем ее или же добавляем еще одну запись?
дело в том, что если зашедший авторизовался, происходит запись в юзерс онлайн, но если он закрыл браузер "раньше положенного", то при следующей авторизации его не пропустит, поскольку запись не удалилась.
 

krafty

new Exception
насчет замены я уже думал (см. пост от 15:12):
PHP:
//авторизация прошла успешно

$logged_user=$login;
  //запоминаем имя пользователя
  $_SESSION['logged_user']=$logged_user;
  $res=mysql_query('SELECT * FROM  users_online');
  $n=mysql_num_rows($res);
  for ($i=0; $i<$n; $i++)
  {
    $f=mysql_fetch_assoc($res);
    $usr_online['login'][]=$f['login'];
    $usr_online['id'][]=$f['id'];
  }
  $in_table=0;
  //проверяем список юзеров в таблице users_online
  for ($i=0; $i<=count($usr_online['login']); $i++)
  {
    if ($usr_online['login'][$i]==$logged_user)
	{
	  $in_table=1;
      $id=$usr_online['id'][$i];
	  break;
	}
  }
  switch ($in_table)
  {
    //записи $logged_user нет в таблице - просто добавляем новую
    case 0:
    mysql_query('INSERT INTO users_online (id, login, online_since, sid) VALUES (\'\',\''.$login.'\',\''.$curr_date.'\',\''.session_id().'\')');
    break;
    //запись есть - обновляем старую
    case 1:
       mysql_query("UPDATE users_online SET online_since = '".$curr_date."', sid='".session_id()."' WHERE id=".$id." LIMIT 1")
    break;
  }
   //перенаправляем на страницу администрирования
    header('Location: admin.php');
  }
что-то вроде этого. но еще не отлаживал
 

Фанат

oncle terrible
Команда форума
$res=mysql_query('SELECT * FROM users_online');
break;
мощный кусок кода
внушает.
считать ВСЮ таблицу.( в место того, чтобы только прочерить наличие нужной строки)
записать в массив (вместо того, чтобы на месте проверять)
и только потом, перебирая массив, искать нужное значение.
три действия вместо одного.
у вас там, на дельфи, всегда так пишут?

-~{}~ 13.08.05 17:45:

(\'\',\''.$login.'\',\''.$curr_date.'\',\''.session_id().'\')');
интересно.
это что за лес густой ты тут вырастил?
что означают все эти палки, которые ты наставил?

-~{}~ 13.08.05 17:48:

а свитч вместо ифа тебя тоже научили на дельфи писать?
не проовал вместо
switch ($in_table)
{
case 0:
mysql_query(
break;
case 1:
mysql_query(
break;
}
написать
if ($in_table) {
mysql_query(
else
mysql_query(
}
?
 

krafty

new Exception
на делфи меня никто не учил писать!
PHP:
  $logged_user=$login;
  $_SESSION['logged_user']=$logged_user;
  $res=mysql_query("SELECT * FROM  users_online WHERE login LIKE '".$logged_user."'");
  $n=mysql_num_rows($res);
  $in_table=1;
  if ($n==0) $in_table=0;
  else $f=mysql_fetch_assoc($res);
  if ($in_table)
     mysql_query("UPDATE users_online SET online_since = '".$curr_date."', sid='".session_id()."' WHERE id=".$f['id']." LIMIT 1");
 else
   mysql_query('INSERT INTO users_online (id, login, online_since, sid) VALUES ("'',".$login."','''.$curr_date."','''.session_id()."')");
    header('Location: admin.php');
-~{}~ 13.08.05 17:02:

примерно так
 

Фанат

oncle terrible
Команда форума
$n=mysql_num_rows($res);
$in_table=1;
if ($n==0) $in_table=0;
тебе не кажется, что две строчки здесь лишние?
а точнее, все три?

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

-~{}~ 13.08.05 18:03:

$n=mysql_num_rows($res);
$in_table=1;
if ($n==0) $in_table=0;
else $f=mysql_fetch_assoc($res);
if ($in_table)
вот это всё заменяется на одну строчку, объединением первой и последней.
то есть, можно, конечно, для строгости, оставить первую и послежнюю раздельно, но уж две средние - это натуральная бессмыслица.
 
Сверху