Этот урок связан с проектом Создание регистрации на сайте на PHP + MySQL

Создание регистрации на сайте на PHP + MySQL. Часть IV

Здравствуйте! Это уже 4-я часть статьи, а вот первая, вторая и третья.
В этой статье мы добавим к нашей регистрации проверку e-mail адреса, автоматический вход и восстановление забытого пароля. Прежде чем приступать к выполнению урока, убедитесь, что у Вас на сервере работает функция mail().

sourse

Начнем с добавления полей в таблицу «users». Нам нужно поле для хранения e-mail адреса, поле для состояния пользователя (0 – неактивирован, 1 - активирован) и поле с датой регистрации.

Далее нам необходимо вывести поле, в которое пользователь будет вписывать свой e-mail. Откроем reg.php и после ввода пароля добавим следующий код:

<!--    В поле для паролей (name="password" type="password") пользователь вводит свой пароль -->  
  <p>
    <label>Ваш E-mail *:<br></label>
    <input name="email" type="text" size="15" maxlength="100">
  </p>
<!-- Вводим е-майл --> 

Затем нужно подправить save_user.php, добавив проверку на корректность e-mail адреса и отправку письма для подтверждения регистрации. В письме находится ссылка с двумя переменными, передающимися методом get: логин и сгенерированный, уникальный для каждого пользователя, код. Код нам нужен, чтобы пользователь не смог активировать свой аккаунт без письма, а это даст нам уверенность, что введенный адрес почты, действительно, принадлежит ему.  Добавим следующий код, после извлечения из глобальных переменных отправленных данных:

if    (isset($_POST['email'])) { $email = $_POST['email']; if ($email == '') {    unset($email);} } //заносим введенный пользователем e-mail, если он    пустой, то уничтожаем переменную
if (empty($login) or empty($password)or empty($code) or empty($email))
//добавим переменную с e-mail адресом
//если пользователь не ввел логин или пароль, то выдаем ошибку и останавливаем скрипт
{
exit ("Вы ввели не всю информацию, вернитесь назад и заполните все поля!"); //останавливаем выполнение сценариев
}
if (!preg_match("/[0-9a-z_]+@[0-9a-z_^\.]+\.[a-z]{2,3}/i", $email)) //проверка е-mail адреса регулярными выражениями на корректность
{exit ("Неверно введен е-mail!");}

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

//    если такого нет, то сохраняем данные
$result2 = mysql_query ("INSERT INTO users (login,password,avatar,email,date) VALUES('$login','$password','$avatar','$email',NOW())");
// Проверяем, есть ли ошибки
if ($result2=='TRUE')
{
$result3 = mysql_query ("SELECT id FROM users WHERE login='$login'",$db);//извлекаем идентификатор пользователя. Благодаря ему у нас и будет уникальный код активации, ведь двух одинаковых идентификаторов быть не может.
$myrow3 = mysql_fetch_array($result3);
$activation = md5($myrow3['id']).md5($login);//код активации аккаунта. Зашифруем через функцию md5 идентификатор и логин. Такое сочетание пользователь вряд ли сможет подобрать вручную через адресную строку.
$subject = "Подтверждение регистрации";//тема сообщения
$message = "Здравствуйте! Спасибо за регистрацию на citename.ru\nВаш логин: ".$login."\n
Перейдите по ссылке, чтобы активировать ваш аккаунт:\nhttp://localhost/test3/activation.php?login=".$login."&code=".$activation."\nС уважением,\n
Администрация citename.ru";//содержание сообщение
mail($email, $subject, $message, "Content-type:text/plane; Charset=windows-1251\r\n");//отправляем сообщение
        
echo "Вам на E-mail выслано письмо с cсылкой, для подтверждения регистрации. Внимание! Ссылка действительна 1 час. <a href='index.php'>Главная страница</a>"; //говорим о отправленном письме пользователю
}

Сообщение отправлено! Теперь пользователь откроет его и перейдет по указанной ссылке на страницу, которая будет проверять код активации. Убедившись, что код верный, мы подтверждаем регистрацию, меняя в базе значение поля activation с «0» на «1».

Создаем файл activation.php

<?php
include ("bd.php");// файл bd.php должен быть в той же папке, что и все остальные, если это не так, то просто измените путь
$result4 = mysql_query ("SELECT avatar FROM users WHERE activation='0' AND UNIX_TIMESTAMP() - UNIX_TIMESTAMP(date) > 3600");//извлекаем аватарки тех пользователей, которые в течении часа не активировали свой аккаунт. Следовательно их надо удалить из базы, а так же и файлы их аватарок
if (mysql_num_rows($result4) > 0) {
$myrow4 = mysql_fetch_array($result4); 
do
{
//удаляем аватары в цикле, если они не стандартные
if ($myrow4['avatar'] == "avatars/net-avatara.jpg") {$a = "Ничего не делать";}
else {
         unlink ($myrow4['avatar']);//удаляем файл
         }
}
while($myrow4 = mysql_fetch_array($result4));
}
mysql_query ("DELETE FROM users WHERE activation='0' AND UNIX_TIMESTAMP() - UNIX_TIMESTAMP(date) > 3600");//удаляем пользователей из базы
if (isset($_GET['code'])) {$code =$_GET['code']; } //код подтверждения
else
{ exit("Вы зашли на страницу без кода подтверждения!");} //если не указали code, то выдаем ошибку
if (isset($_GET['login'])) {$login=$_GET['login']; } //логин,который нужно активировать
else
{ exit("Вы зашли на страницу без логина!");} //если не указали логин, то выдаем ошибку
$result = mysql_query("SELECT id FROM users WHERE login='$login'",$db); //извлекаем идентификатор пользователя с данным логином
$myrow = mysql_fetch_array($result);
$activation = md5($myrow['id']).md5($login);//создаем такой же код подтверждения
if ($activation == $code) {//сравниваем полученный из url и сгенерированный код
         mysql_query("UPDATE users SET activation='1' WHERE login='$login'",$db);//если равны, то активируем пользователя
         echo "Ваш Е-мейл подтвержден! Теперь вы можете зайти на сайт под своим логином! <a href='index.php'>Главная страница</a>";
         }
else {echo "Ошибка! Ваш Е-мейл не подтвержден! <a href='index.php'>Главная страница</a>";
//если же полученный из url и сгенерированный код не равны, то выдаем ошибку
}
?>

E-mail адрес подтвержден, теперь мы знаем, что этот адрес принадлежит данному пользователю, на него можно будет послать пароль, если пользователь его забудет, или другие уведомления. Но в чем различие активированных пользователей, от неактивированных? И те и другие могут зайти на сайт, следовательно, нам нужно ограничить в доступе неактивированных. Откроем файл testreg.php и допишем еще одно условие в запросе к базе:

$result = mysql_query("SELECT * FROM    users WHERE login='$login' AND    password='$password'    AND    activation='1'",$db); //извлекаем    из базы все данные о пользователе с введенным логином
//мы дописали «AND activation='1'», то есть пользователь будет искаться только среди активированных. Желательно добавить это условие к другим подобным проверкам данных пользователя

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

index.php

<p>
    <input name="autovhod" type="checkbox" value='1'> Автоматический вход.
  </p>
<p>
<input type="submit" name="submit" value="Войти">
<!-- Кнопочка (type="submit") отправляет данные на страничку testreg.php  -->
<br>
<!-- ссылка на регистрацию, ведь как-то же должны гости туда попадать  -->
<a href="reg.php">Зарегистрироваться</a>
<br>
<!-- ссылка на восстановление пароля  -->
<a href="send_pass.php">Забыли пароль?</a>

Ссылка есть, а файла нет. Давайте же напишем send_pass.php. В нем мы спросим у пользователя логин и адрес почты. Если введенный e-mail и логин есть в базе, то отправим на него новый пароль, если пользователь забыл старый, ведь мы убедились при регистрации, что адрес почты действителен.

<?php
if (isset($_POST['login'])) { $login = $_POST['login']; if ($login == '') { unset($login);} } //заносим введенный пользователем логин в переменную $login, если он пустой, то уничтожаем переменную
if (isset($_POST['email'])) { $email = $_POST['email']; if ($email == '') { unset($email);} } //заносим введенный пользователем e-mail, если он пустой, то уничтожаем переменную
if (isset($login) and isset($email)) {//если существуют необходимые переменные 
        
         include ("bd.php");// файл bd.php должен быть в той же папке, что и все остальные, если это не так, то просто измените путь
        
         $result = mysql_query("SELECT id FROM users WHERE login='$login' AND email='$email' AND activation='1'",$db);//такой ли у пользователя е-мейл
         $myrow = mysql_fetch_array($result);
         if (empty($myrow['id']) or $myrow['id']=='') {
                  //если активированного пользователя с таким логином и е-mail адресом нет
                  exit ("Пользователя с таким e-mail адресом не обнаружено ни в одной базе ЦРУ :) <a href='index.php'>Главная страница</a>");
                  }
         //если пользователь с таким логином и е-мейлом найден, то необходимо сгенерировать для него случайный пароль, обновить его в базе и отправить на е-мейл
         $datenow = date('YmdHis');//извлекаем дату
         $new_password = md5($datenow);// шифруем дату
         $new_password = substr($new_password, 2, 6); //извлекаем из шифра 6 символов начиная со второго. Это и будет наш случайный пароль. Далее запишем его в базу, зашифровав точно так же, как и обычно.
        
$new_password_sh = strrev(md5($new_password))."b3p6f";//зашифровали
mysql_query("UPDATE users SET password='$new_password_sh' WHERE login='$login'",$db);// обновили в базе
         //формируем сообщение
        
         $message = "Здравствуйте, ".$login."! Мы сгененриоровали для Вас пароль, теперь Вы сможете войти на сайт citename.ru, используя его. После входа желательно его сменить. Пароль:\n".$new_password;//текст сообщения
         mail($email, "Восстановление пароля", $message, "Content-type:text/plane; Charset=windows-1251\r\n");//отправляем сообщение
        
         echo "<html><head><meta http-equiv='Refresh' content='5; URL=index.php'></head><body>На Ваш e-mail отправлено письмо с паролем. Вы будете перемещены через 5 сек. Если не хотите ждать, то <a href='index.php'>нажмите сюда.</a></body></html>";//перенаправляем пользователя
         }
else {//если данные еще не введены
echo '
<html>
<head>
<title>Забыли пароль?</title>
</head>
<body>
<h2>Забыли пароль?</h2>
<form action="#" method="post">
Введите Ваш логин:<br> <input type="text" name="login"><br><br>
Введите Ваш E-mail: <br><input type="text" name="email"><br><br>
<input type="submit" name="submit" value="Отправить">
</form>
</body>
</html>';
}
?>

Далее мы сделаем автоматический вход. Работать он будет так: при удачном входе с нажатым чекбоксом в cookie будет вписываться auto = “yes”. Если сервер увидит, что в браузере  auto = “yes”, то запустит сессию, а переменные возьмет там же, в cookie. Затем идет проверка запущенных сессий по базе.

Откроем testreg.php и допишем после удачного входа код:

if    (isset($_POST['save'])){
//Если пользователь хочет, чтобы его данные сохранились для последующего входа, то сохраняем в куках его браузера
setcookie("login", $_POST["login"], time()+9999999);
setcookie("password", $_POST["password"], time()+9999999);
setcookie("id", $myrow['id'], time()+9999999);}
if (isset($_POST['autovhod'])){
//Если пользователь хочет входить на сайт автоматически
setcookie("auto", "yes", time()+9999999);
setcookie("login", $_POST["login"], time()+9999999);
setcookie("password", $_POST["password"], time()+9999999);
setcookie("id", $myrow['id'], time()+9999999);}

Теперь надо запустить в нужном месте сессию, если стоит автоматический вход. Откроем index.php и напишем в самом начале страницы:

<?php
// вся процедура работает на сессиях. Именно в ней хранятся данные пользователя, пока он находится на сайте. Очень важно запустить их в самом начале странички!!!
session_start();
include ("bd.php");// файл bd.php должен быть в той же папке, что и все остальные, если это не так, то просто измените путь
if (isset($_COOKIE['auto']) and isset($_COOKIE['login']) and isset($_COOKIE['password']))
{//если есть необходимые переменные
         if ($_COOKIE['auto'] == 'yes') { // если пользователь желает входить автоматически, то запускаем сессии
                    $_SESSION['password']=strrev(md5($_COOKIE['password']))."b3p6f"; //в куках пароль был не зашифрованный, а в сессиях обычно храним зашифрованный
                    $_SESSION['login']=$_COOKIE['login'];//сессия с логином
                    $_SESSION['id']=$_COOKIE['id'];//идентификатор пользователя
                  }       
         }

Вот теперь нам даже выход не поможет, что бы сменить пользователя! В exit.php удаляются сессии, которые все равно создаются на index.php, благодаря cookie, которые хранятся очень долго! Давайте уж все-таки починим файл exit.php, а то он не функционален в случае автоматического входа. Надо всего лишь очистить в cookie автоматический вход, после удаления переменных из сессии:

setcookie("auto", "",    time()+9999999);//очищаем автоматический вход

Так же необходимо добавить в update_user.php после обновления логина в сессии:

$_SESSION['login'] = $login;//Обновляем    логин в сессии
if (isset($_COOKIE['login'])) {
setcookie("login", $login, time()+9999999);//Обновляем логин в куках
}

И то же самое с паролем

$result4 =    mysql_query("UPDATE users SET password='$password' WHERE    login='$old_login'",$db);//обновляем пароль 
if ($result4=='TRUE') {//если верно, то обновляем его в сессии
$_SESSION['password'] = $password;
if (isset($_COOKIE['password'])) {
setcookie("password",$_POST['password'], time()+9999999);//Обновляем пароль в куках, если они есть
}

Ну вот и все. Надеюсь, что у Вас все получится! Удачи!

Автор: Стороженко Евгений
Оформление: Максим Шкурупий

Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: www.ruseller.com
Автор: Максим Шкурупий
Урок создан: 12 Августа 2009
Просмотров: 6274964
Правила перепечатки


5 последних уроков рубрики "PHP"

  • Фильтрация данных с помощью zend-filter

    Когда речь идёт о безопасности веб-сайта, то фраза "фильтруйте всё, экранируйте всё" всегда будет актуальна. Сегодня поговорим о фильтрации данных.

  • Контекстное экранирование с помощью zend-escaper

    Обеспечение безопасности веб-сайта — это не только защита от SQL инъекций, но и протекция от межсайтового скриптинга (XSS), межсайтовой подделки запросов (CSRF) и от других видов атак. В частности, вам нужно очень осторожно подходить к формированию HTML, CSS и JavaScript кода.

  • Подключение Zend модулей к Expressive

    Expressive 2 поддерживает возможность подключения других ZF компонент по специальной схеме. Не всем нравится данное решение. В этой статье мы расскажем как улучшили процесс подключение нескольких модулей.

  • Совет: отправка информации в Google Analytics через API

    Предположим, что вам необходимо отправить какую-то информацию в Google Analytics из серверного скрипта. Как это сделать. Ответ в этой заметке.

  • Подборка PHP песочниц

    Подборка из нескольких видов PHP песочниц. На некоторых вы в режиме online сможете потестить свой код, но есть так же решения, которые можно внедрить на свой сайт.

^ Наверх ^