PDA

Просмотр полной версии : Простая страница восстановления пароля


deadangel
01.06.2010, 09:16
Написал простой скрипт восстановления пароля. Пароль в БД меняется, но в игру все равно заходит по старому паролю. Вопрос, как можно сделать так, чтобы после смены пароля сразу в игру можно было зайти по новому паролю?

Вот окончательный и переделанный вариант скрипта.


<?=header('Content-type: text/html; charset=utf-8');?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru">
<head>
<title>Смена пароля для аккаунта World of Warcraft</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="author" content="Kazakou V. Andrey" />
<meta name="email" content="a.v.kazakou@gmail.com" />
</head>
<body>

<?php
function error($str = '')
{
echo "<p class=\"error\">$str</p></body></html>";
exit;
}

function sendPassword($login, $email)
{
mysql_connect('<host>','<login>','<password>') or die(error('Ошибка! Невозможно соедениться с базой данных.'));
mysql_select_db('realmd');

$login = mysql_real_escape_string($login);
$email = mysql_real_escape_string($email);

$result = mysql_query('SELECT COUNT(*) as validation FROM `account` WHERE `username` LIKE \''.$login.'\' AND `email` LIKE \''.$email.'\'') or die(error('Ошибка! Невозможно выполнить запрос в БД'));
$result = mysql_fetch_array($result);
if($result['validation']!=1) error('Данная связка Логина и E-mail не обнаружена');

$psswd = str_shuffle(substr(md5(rand(1,1024)), 0, 6));
$sql = "UPDATE `account` SET `sha_pass_hash`=SHA1(UPPER(CONCAT('$login',':','$p sswd'))), `locked`=0, `v`=NULL, `s`=NULL, `sessionkey`=NULL WHERE `username`='$login' AND `email`='$email'";
$result = mysql_query($sql) or die(error(mysql_error().'</p><p>'.$sql));
if(mysql_affected_rows()!=1) error('Невозможно изменить пароль в базе данных');

$to = $email;
$subject = 'Смена пароля для World of Warcraft';
$message = 'Ваш новый пароль для аккаунта '.$login.' в игре World of Warcraft: '.$psswd;
$headers = 'From: robot@example.com' . "\r\n" .
'Reply-To: robot@example.com' . "\r\n" .
'Content-type: text/plain; charset=UTF-8' . "\r\n" .
'X-Mailer: PHP/' . phpversion();

$mailSended = mail($to, $subject, $message, $headers);
if(!$mailSended) error('Невозможно отправить письмо с новым паролем.');

error('Письмо с новым паролем выслано на указаный адрес.');
}
?>

<?php
if(!empty($_POST) and isset($_POST['login']) and isset($_POST['email'])) sendPassword($_POST['login'], $_POST['email']);
?>

<form action="newpass.php" method="post">
<table summary="">
<tr>
<td>Имя аккаунта:</td>
<td><input type="text" name="login" value="" size="30" /></td>

</tr>
<tr>
<td>Адрес e-mail:</td>
<td><input type="text" name="email" value="" size="30" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" name="submit" value="Выслать новый пароль" /></td>
</tr>
</table>
</form>
</body>
</html>

Mic
01.06.2010, 09:23
Кажется, нужно по пути обнулить поля "s" и "v". Ну и про экранирование переменных перед подстановкой в запросы тоже не стоит забывать.

Кот ДаWINчи
01.06.2010, 10:48
Кажется, нужно по пути обнулить поля "s" и "v". Ну и про экранирование переменных перед подстановкой в запросы тоже не стоит забывать.

Правильно. И еще можно занулить sessionkey

Вот тут:


$sql = "UPDATE `account` SET `sha_pass_hash`=SHA1(CONCAT(UPPER('$login'),':',UP PER('$psswd'))), `locked`=0 WHERE `username` LIKE '$login' AND `email` LIKE '$email'";

alien
01.06.2010, 18:36
Только использовать LIKE в данном запросе совершенно неверно.
Да и вобще если использовать текущий вариант скрипта не безопасно.

deadangel
02.06.2010, 11:39
Потенциально LIKE конечно опасен, но в конкретном случае я не вижу проблемы, как с его помощью можно взломать БД. Более того, у меня база персонажей хранится уже 3 года и раньше пользователи создавали имена аккаунтов в разном регистре и по сей день вводят их в этом регистре. Если ставить вместо Like условие равенства, то большая часть запорется. Т.к. все аккаунты давно уже хранятся в UP регистре.

Спасибо всем. В запросе установил обнуление полей V, S и sessionkey. пароль начал меняться как положено. Вот работающая версия скрипта. Может кому нибудь и пригодится :)


$psswd = str_shuffle(substr(md5(rand(1,1024)), 0, 6));
$sql = "UPDATE `account` SET `sha_pass_hash`=SHA1(CONCAT(UPPER('$login'),':',UP PER('$psswd'))), `locked`=0, `v`=NULL, `s`=NULL, `sessionkey`=NULL WHERE `username` LIKE '$login' AND `email` LIKE '$email'";
$result = mysql_query($sql) or die(error(mysql_error().'</p><p>'.$sql));

alien
02.06.2010, 11:58
Вместо использования достачно внести в настройки sql нечуствительность регистра при равенстве.
А помешать очень просто можно сбросить пароль другому человеку.

deadangel
02.06.2010, 12:18
Согласен. Если добавить % в имя пользователя, то как вариант он сбросит пароли. В таком случае придется делать регистронезависимое сравнение и для e-mail. :) Сейчас переделаю и сброшу окончательный вариант.

deadangel
02.06.2010, 14:16
Вот окончательный вариант скрипта перенес в первый пост. Кто нибудь может подсказать его потенциально опасные моменты? В принципе у меня сервер настроен на независимость регистров при сравнении. Но если кому-то понадобится, то проще данные пользователя и БД приводить к верхнему регистру. :) В общем всех благодарю за помощь.

tempura
02.06.2010, 16:38
Оба молодцы! :)


Простите, но просто вот ради именно такого общения и создан форум. Не ради "дайти ресофку скочадь", а ради вас, ребята! :)

Mic
04.06.2010, 11:21
if(!empty($_POST)) sendPassword($_POST['login'], $_POST['email']); - потенциальный источник notice'ов. Массив-то может и не пустой, но этих элементов там может не быть.
Ну и мелкая придирочка ;) CONCAT(UPPER('foo'), ':', UPPER('bar')) == UPPER(CONCAT('foo', ':', 'bar'))

deadangel
04.06.2010, 14:49
Поправил скрипт в первом посте. Спасибо за информацию :)