[php]Проблемма с $_SESSION

iakobi91

Есть два файла. Превый отсылает данные из формы на второй - log.php.
Форма в первом:
<form name="login" method="post" action="log.php" onSubmit="doSend">
...
<input type="hidden" value="<?=$nonce?>" name="nonce">
<input type="hidden" value="" name="password">
...
</form>
Начало обработки файла в log.php:
<?php
session_start;
if (!isset($_SESSION['nonce']) ) die('Illegal challenge response. Possible hack');
Прога выдаёт 'Illegal challenge response. Possible hack'.
В чём фишка?
track_vars = On
register_globals = On или Off - нет разницы, не работает.

stm7884696

ну во первых, если ты поставишь в первом файле session_register("nonce");
то оно заработает, т.к. тогда ты зарегишь эту переменную в сессию...
Или же во втором файле тебе надо проверять не сессионную переменную, а массив $_POST, т.к. данные из формы ты передаешь постом, а не сессией...
И втретьих, напиши, что ты глобально хотел сделать, может эта проблема решена более простым способом ?

iakobi91

Пытаюсь запустить вот это - аутентификация пользователя.
Проблема - сделать аутентификацию пользователя. Вот предложили эту ссылку, теперь с ней вожусь.
Стоит php 4.3.0 из денвера. Вроде всё должно работать.

stm7884696

я хз, но у меня этот url не открывается...
может опишеь, что там ?

iakobi91

Существенным требованием к средствам авторизации есть гибкость, которая не всегда достигается стандарнтыми методам. Не всегда можно сконфигурировать сервер для защищенного SSL канала, а обычные средства авторизации (HTTP, сессии) не обеспечивают надежной защиты. Данный метод полностью системно независим и использует только PHP на стороне сервера и JavaScript на стороне клиента. Используется только стандартная функция MD5 (32-битное хеширование, RSA Message Digest Algorytm JS имплементацию которой любезно предоставил Генри Торжман.
MD5 JavaScript
Скачайте себе md5.js который делает MD5 хеш из любой строки. Есть несколько версий его имплементции на JavaScript:
http://opensource.polytechnique.org/cvs/diogenes/md5.js?cvsroot=Public#rev1.1
http://pajhome.org.uk/crypt/md5/md5src.html
http://www.myersdaily.org/joseph/javascript/md5.js
http://www.onicos.com/staff/iz/amuse/javascript/expert/md5.txt
Данные имплементации не проверена на совместимость с non-ascii символами. Вероятнее всего кириллица не будет правильно хешироваться. Также скрипт о-очень медленно работает на броузере Opera 6. Также нужно проверять включена ли поддержка javascript вообще (об этом позже).
Суть метода
Идея авторизации лежит в том, что клиент посылает логин и пароль через обычную форму, но в зашифрованном с помощью случайного ключа виде (challenge response). Без случайного ключа хеширование не было бы оправдано, а в нашем случае, если злоумышленник перехватит хеш, он не сможет его использовать, потому что сервер уже не знает того случайного ключа ($nonce который посылался для хеширования. Для того, чтобы из перехваченных данных получить пароль, лучшего метода чем перебор не существует. При соответствуюших требованиях к паролю усилия на расшифрование будут неоправданы.
Хотя метод достаточно защищеныний, его надежность компрометируется самим механизмом сессий, который предусматривает передачу идентификатора сессии в открытом виде (через УРЛ или Куку). К тому же метод нету смысла использовать для защиты самой информации (информация все равно идет открітім каналом а только для ограничения доступа к редактированию динамического контента
Реализация
Для авторизации необходимо создать 2 PHP скрипта. Первый генерирует случайную строку и посылает клиенту вместе с формой логина и пароля. Даная форма обрабатывается JS, который шифрует введенный пароль и отсылает на другой скрипт. Другой скрипт помнит этот ключ, получает зашифрованный пароль и логин, находит в своей базе (в нашем примере MySQL таблица) соответствующий логину пароль (точнее соответствующий ему MD5 хеш). Он той же функцией MD5, хеширует и сверяет с полученной строкой. Если все этапы прошли успешно на клинте открывается идентификатор сесии, который дает ему право работать с защищенными скриптами.
Теперь к тому как это все работает
Файл login.php
<?php
function make_seed {
list($usec, $sec) = explode (' ', microtime;
return (float) $sec + float) $usec * 100000);
}
mt_srand(make_seed;
$nonce=mt_rand(1, 10000000); #генерируем слуайное число
$nonce=md5($nonce); #превращаем это число в случайную строку
$_SESSION['nonce']=$nonce; #запоминаем наш случайный ключ к следуйщей странице
?>
<html>
<head>
<script language="javascript" src=md5.js>
</script>
<script language="javascript">
function doSend{
document.login.password.value=MD5(document.login.pass.value);
document.login.password.value=MD5(document.login.password.value+document.login.nonce.value);
document.login.pass.value=''; // NOT to send password as a plain text
document.login.nonce.value='';// NOT to send random key
}
</script>
</head>
<body>
<form name="login" method="post" action="loginrespond.php" onSubmit="doSend">
<input type="text" name="login" value="<?=@$_COOKIE['lastlogged']?>">
<input type="password" name="pass">
<input type="submit" value="Log in">
<input type="hidden" value="<?=$nonce?>" name="nonce">
<input type="hidden" value="" name="password">
</form>
</body>
</html>
Дальше необходимо обработать результат отсылки формы авторизации:
loginrespond.php
<?php
session_start;
if (!isset($_SESSION['nonce']) || strlen($_SESSION['nonce'])!=32) die('Illegal challenge response. Possible hack');
#--------- Получение пароля из MySQL-----------------
#- Здесь может быть любой способ получения пароля--
$host='localhost'; $user='inet'; $pass='po32jlkdjl3'; $db='baza';
mysql_connect($host, $user, $pass);
mysql_select_db($db);
$sql="SELECT * FROM tblusers WHERE login='".Trim(@$_POST['login']);
$sql.="' AND activate=1 AND MD5(CONCAT(pass, '".$_SESSION['nonce']."'='".$_POST['password']."'";
$result = @mysql_query($sql) or die('Query failure: '.mysql_error;
if (!mysql_num_rows($result {
die('Неправильный логин или пароль');
} else {
$row=mysql_fetch_array($result);
mysql_free_result($result);
if ($row['requireip']) {
$sql='SELECT * FROM tblip WHERE ip='.ip2long($_SERVER['REMOTE_ADDR']);
$result=$mysql_query($sql);
if (!mysql_num_rows($result {
$msg="<span class=hot>".$_SERVER['REMOTE_ADDR'].":</span><br>";
$msg.="Запрещена работа с этого IP";
die($msg);
}
}
if (isset($row['expires'] {
if (strtotime($row['expires'])<time die('Строк действия вашего доступа исчерпан');
}
// присваиваем переменной сессии уровень доступа для данного юзера
$_SESSION['auth']=$row['authlevel'];
$_SESSION['userid']=(int) $row['id'];
$_SESSION['username']=$row['name'];
/* PHPSESSID Anti-spoofing */
$_SESSION['REMOTE_ADDR']=$_SERVER['REMOTE_ADDR'];
$_SESSION['HTTP_X_FORWARDED_FOR']=@$_SERVER['HTTP_X_FORWARDED_FOR'];
$_SESSION['HTTP_USER_AGENT']=$_SERVER['HTTP_USER_AGENT'];
// запоминаем в куку логин пользователя
setcookie("lastlogged", $row['login'],time+3600*24*30);
header("Location: protected.php");
exit;
}
?>
В приведенном скрипте мы кроме простого сверения паролей проделали ряд полезных вещей
Проверка WHERE activate=1 дает возможность временно отключать юзерам доступ (activate=0)
Проверка поля expires (срок, когда доступ истекат). Если поле не NULL, то проверяется наступила ли уже указання дата
Если поле requireip установлено, то выполняется дополнительная привязка юзера к списку IP-адресов (в нашем случае дополнительная MySQL таблица)
Здесь можно задать общий список white list или привязывать конкретных юзеров к конкретным IP (по userid). Используйте эту проверку осторожно, например если вы постоянно работаете из некоторых IP и хотите вообще ограничить заход с других IP даже если пароль был скомпрометир

stm7884696

насколько я понимаю, данная строка
$_SESSION['nonce']=$nonce; #запоминаем наш случайный ключ к следуйщей странице   
абсолютно ничего не делает...
Для начала надо бы запустить сессию, (session_start;)? а уже потом писать в нее переменные...
И лучше ИМХО писать session_register("имя_переменной");
что бы ее зарегистрить...
Попробуй....

iakobi91

Спасибо, буду пробовать

iakobi91

Не работает.

stm7884696

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

iakobi91

Всё так и делал. Но получилось через $_POST - данные пересылает, пароль проверяет. Только я не понял, зачем нужет 'nonce'.

stm7884696

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

Fragaria

Лёх, не уверен, но по-моему при работе с $_SESSION не нужно делать session_register почитай php_manual, я на линухе, поэтому пока не могу.

IvladV71

>я на линухе, поэтому пока не могу.
а в чём проблема?

stalker33rus10

Да, абсолютно верно, session_register остался по-моему с тех времен когда register_globals было on.
Вобще достаточно внести в $_SESSION["переменная"] значение и она зарегится. по крайней мере при дефолтных настройках.

stm7884696

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

iakobi91

Разобрался с сессиями. Всё работает, пароль хеширует, передаёт, проверяет и тд.

stm7884696

так че там было то ?
Нам тоже интересно...

iakobi91

Просто не до конца разобрался. Нужно было каждый раз сессию открывать, а я думал, что раз открыл и всё. Вообщем "проект" я закончил, всем спасибо за помощь
Оставить комментарий
Имя или ник:
Комментарий: