—»     —»   Создаем невероятную простую систему регистрации на PHP и MySQL
  Раздел: Руководства   Комментариев: 4  

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



Процесс создания системы регистрации – это довольно большой объем работы. Вам нужно написать код, который бы перепроверял валидность email-адресов, высылал email-письма с подтверждением, предлагал возможность восстановить пароль, хранил бы пароли в безопасном месте, проверял формы ввода и многое другое. Даже когда вы все это сделаете, пользователи будут регистрироваться неохотно, так как даже самая минимальная регистрация требует их активности.

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

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

Демо | Скачать
Внимание! У вас нет прав для просмотра скрытого текста.


Суть

Давайте посмотрим, как эта простая система регистрации работает:

* У нас будет использоваться комбинированная форма авторизации/регистрации, где пользователи смогут вводить email и нажимать на кнопку подтверждения;
* При подтверждении, если email-адрес не обнаружен в базе данных, в нее вносится новая запись. Генерируется случайная лексема и отправляется пользователю по email в виде кликабельной ссылки, которая будет действовать всего 10 минут;
* Клик по ссылке во входящих сообщениях перекинет пользователя снова на страницу сайта. Система определит присутствие лексемы и авторизует пользователя.

Данный подход имеет следующие преимущества:

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

Однако есть и следующие недостатки:

* Безопасность основывается на безопасности почтового ящика человека. Если кто-то завладеет данными от его почтового ящика, то этот злоумышленник получит доступ и к этой системе. Конечно, подобная проблема существует и с функциями восстановления паролей по email, но вы просто должны об этом знать;
* Email не защищен и может быть перехвачен. Учитывайте, что здесь, как и в случае с формой восстановления паролей, не используется HTTPS-передача данных, и данные могут быть перехвачены злоумышленником;
* Пока вы не настроите исходящие сообщения, существует вероятность, что ваша система просто «заспамит» чей-то почтовый ящик;

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

Применение системы регистрации

В том случае, если вы просто хотите использовать нашу систему регистрации на вашем сайте, и не хотите изучать руководство, то вам нужно сделать следующее:

* Сначала нужно скачать вышеприведенный zip-файл;
* В zip-файле найти файл tables.sql. Импортировать его в базу данных, используя опцию импорта в phpmyadmin. С другой стороны, вы можете открыть файл в текстовом редакторе, скопировать SQL и запустить его;
* Откройте includes/main.php, и внесите туда данные для соединения с базой данных, а также комбинацию логин/пароль. В том же файле вам также нужно добавить email, который будет использовать в качестве отправителя сообщений. Некоторые веб-хостинги блокируют исходящие сообщения до тех пор, пока вы не укажите настоящий email-адрес, который можно создать при помощи панели управления этого же хостера;
* Загрузите все необходимые файлы посредством FTP или других способов;
* Добавьте предпоследний фрагмент кода (см. ниже) на каждую PHP-страницу, которые должны стать доступными только после авторизации;
* Веселитесь!

Те, кто решил остаться с нами и дочитать статью до конца, предлагаем дальнейшую информацию:

HMTL-код

Первый этап заключается в создании HTML-кода для формы авторизации. Следующий HTML-код находится в index.php. Этот файл также хранит в себе PHP-код, который отвечает за подтверждение формы и другие полезные функции нашей системы авторизации. Вы узнаете об этом подробнее в разделе с PHP-кодом.

Index.php

<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8"/>
<title>Tutorial: Super Simple Registration System With PHP &amp; MySQL</title>

<!-- The main CSS file -->
<link href="assets/css/style.css" rel="stylesheet" />

<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>

<body>

<form id="login-register" method="post" action="index.php">

<h1>Login or Register</h1>

<input type="text" placeholder="your@email.com" name="email" autofocus />
<p>Enter your email address above and we will send <br />you a login link.</p>

<button type="submit">Login / Register</button>

<span></span>

</form>

<!-- javascript Includes -->
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="assets/js/script.js"></script>

</body>
</html>

В головной раздел мы включили основные таблицы стилей (они не представлены в руководстве, поэтому вам нужно будет открыть файл в редакторе, чтобы ознакомиться с ними). Перед закрывающих тегом body мы включили jQuery-библиотеку и файл script.js, разработкой которого мы займемся в следующем разделе статьи.

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

Теперь давайте займемся jQuery!

javascript-код

jQuery ожидает событие формы submit, запускает e.preventDefault(), и отправляет AJAX-запрос. В зависимости от ответа сервера, он отображает сообщение и предотвращает дальнейшее подтверждение.

assets/js/script.js

$(function(){

var form = $('#login-register');

form.on('submit', function(e){

if(form.is('.loading, .loggedIn')){
return false;
}

var email = form.find('input').val(),
messageHolder = form.find('span');

e.preventDefault();

$.post(this.action, {email: email}, function(m){

if(m.error){
form.addClass('error');
messageHolder.text(m.message);
}
else{
form.removeClass('error').addClass('loggedIn');
messageHolder.text(m.message);
}
});

});

$(document).ajaxStart(function(){
form.addClass('loading');
});

$(document).ajaxComplete(function(){
form.removeClass('loading');
});
});

CSS-класс .loading добавляется к форме посредством Ajax-запроса в самом начале (это возможно благодаря методам ajaxStart() и ajaxComplete(), которые вы можете видеть практически в конце файла). Этот CSS-класс позволяет отобразить вращающийся индикатор, и вдобавок выступает в роли маркера, предотвращающего двойного подтверждения формы. Класс .loggedIn – это еще один маркер, который устанавливается как только email-сообщение будет отправлено. Он сразу же блокирует любые дальнейшие подтверждения.

Структура базы данных

Нашей простой системе регистрации понадобится 2 MySQL-таблицы (SQL-код вы можете видеть в файле tables.sql в zip-архиве). Первая таблица содержит пользовательские аккаунты, а вторая будет хранить данные о попытках авторизации.

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

Система не использует паролей, что приводит к отсутствию поля password в структуре. Здесь есть колонка token вместе с колонкой token_validity. Token (лексема) устанавливается, когда пользователь авторизуется в систему, и высылается на указанный пользователем email (подробнее об этом в следующем разделе). Затем token_validity устанавливается на 10 минут, после чего token станет недействительным.

Каждый раз, когда кто-нибудь пытается авторизоваться, во вторую таблицу вписывается новая запись. Как видно в нашем PHP-коде, благодаря этому у нас есть возможность реализовать ограничение количества попыток по IP-адресу. Мы устанавливаем ограничение в 10 попыток за 10 минут, и ограничение в 20 попыток в течение часа. Большее количество попыток приведет к блокировке IP-адреса.

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

В обеих таблицах IP-адрес хранится в виде целого числа с использованием PHP-функции ip2long.

PHP

Теперь мы готовы к тому, чтобы заняться кодом PHP. Основной функционал системы регистрации предоставляется классом User, который вы можете видеть ниже. Класс использует Idorm (документация), представляющую собой минималистскую библиотеку для работы с базами данных. Класс User отвечает за доступ к базам данных, генерирование token-ов для логина и их валидации. Он представляет нам простой интерфейс, который можно без труда включить в систему регистрации на ваших сайтах, основанных на PHP.

User.class.php

class User{

// Private ORM instance
private $orm;

/**
* Find a user by a token string. Only valid tokens are taken into
* consideration. A token is valid for 10 minutes after it has been generated.
* @param string $token The token to search for
* @return User
*/

public static function findByToken($token){

// find it in the database and make sure the timestamp is correct

$result = ORM::for_table('reg_users')
->where('token', $token)
->where_raw('token_validity > NOW()')
->find_one();

if(!$result){
return false;
}

return new User($result);
}

/**
* Either login or register a user.
* @param string $email The user's email address
* @return User
*/

public static function loginOrRegister($email){

// If such a user already exists, return it

if(User::exists($email)){
return new User($email);
}

// Otherwise, create it and return it

return User::create($email);
}

/**
* Create a new user and save it to the database
* @param string $email The user's email address
* @return User
*/

private static function create($email){

// Write a new user to the database and return it

$result = ORM::for_table('reg_users')->create();
$result->email = $email;
$result->save();

return new User($result);
}

/**
* Check whether such a user exists in the database and return a boolean.
* @param string $email The user's email address
* @return boolean
*/

public static function exists($email){

// Does the user exist in the database?
$result = ORM::for_table('reg_users')
->where('email', $email)
->count();

return $result == 1;
}

/**
* Create a new user object
* @param $param ORM instance, id, email or null
* @return User
*/

public function __construct($param = null){

if($param instanceof ORM){

// An ORM instance was passed
$this->orm = $param;
}
else if(is_string($param)){

// An email was passed
$this->orm = ORM::for_table('reg_users')
->where('email', $param)
->find_one();
}
else{

$id = 0;

if(is_numeric($param)){
// A user id was passed as a parameter
$id = $param;
}
else if(isset($_SESSION['loginid'])){

// No user ID was passed, look into the sesion
$id = $_SESSION['loginid'];
}

$this->orm = ORM::for_table('reg_users')
->where('id', $id)
->find_one();
}

}

/**
* Generates a new SHA1 login token, writes it to the database and returns it.
* @return string
*/

public function generateToken(){
// generate a token for the logged in user. Save it to the database.

$token = sha1($this->email.time().rand(0, 1000000));

// Save the token to the database,
// and mark it as valid for the next 10 minutes only

$this->orm->set('token', $token);
$this->orm->set_expr('token_validity', "ADDTIME(NOW(),'0:10')");
$this->orm->save();

return $token;
}

/**
* Login this user
* @return void
*/

public function login(){

// Mark the user as logged in
$_SESSION['loginid'] = $this->orm->id;

// Update the last_login db field
$this->orm->set_expr('last_login', 'NOW()');
$this->orm->save();
}

/**
* Destroy the session and logout the user.
* @return void
*/

public function logout(){
$_SESSION = array();
unset($_SESSION);
}

/**
* Check whether the user is logged in.
* @return boolean
*/

public function loggedIn(){
return isset($this->orm->id) && $_SESSION['loginid'] == $this->orm->id;
}

/**
* Check whether the user is an administrator
* @return boolean
*/

public function isAdmin(){
return $this->rank() == 'administrator';
}

/**
* Find the type of user. It can be either admin or regular.
* @return string
*/

public function rank(){
if($this->orm->rank == 1){
return 'administrator';
}

return 'regular';
}

/**
* Magic method for accessing the elements of the private
* $orm instance as properties of the user object
* @param string $key The accessed property's name
* @return mixed
*/

public function __get($key){
if(isset($this->orm->$key)){
return $this->orm->$key;
}

return null;
}
}

Token-ы генерируются при помощи алгоритма SHA1, и сохраняются в базу данных. Мы используем функции даты и времени из MySQL для установки значения в колонку token_validity, равного 10 минутам. При валидации token, мы сообщаем движку, что нам нужен token, поле token_validity пока еще не истекло. Таким образом мы ограничиваем время, в течение которого token будет валиден.

Обратите внимание на то, что мы используем волшебный метод __get (документация) в конце документа, чтобы получить доступ к свойствам объекта user. Это позволяет нам осуществить доступ к данным, которые хранятся в базе данных в виде свойств: $user->email, $user->token. Для примера давайте посмотрим, как мы можем использовать этот класс в следующем фрагменте кода:

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

Еще один файл, в котором хранится необходимый функционал, это functions.php. Там у нас есть несколько вспомогательных функций, которые позволяют нам сохранить остальной код более опрятным.

Functions.php

function send_email($from, $to, $subject, $message){

// Helper function for sending email

$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/plain; charset=utf-8' . "\r\n";
$headers .= 'From: '.$from . "\r\n";

return mail($to, $subject, $message, $headers);
}

function get_page_url(){

// Find out the URL of a PHP file

$url = 'http'.(empty($_SERVER['HTTPS'])?'':'s').'://'.$_SERVER['SERVER_NAME'];

if(isset($_SERVER['REQUEST_URI']) && $_SERVER['REQUEST_URI'] != ''){
$url.= $_SERVER['REQUEST_URI'];
}
else{
$url.= $_SERVER['PATH_INFO'];
}

return $url;
}

function rate_limit($ip, $limit_hour = 20, $limit_10_min = 10){

// The number of login attempts for the last hour by this IP address

$count_hour = ORM::for_table('reg_login_attempt')
->where('ip', sprintf("%u", ip2long($ip)))
->where_raw("ts > SUBTIME(NOW(),'1:00')")
->count();

// The number of login attempts for the last 10 minutes by this IP address

$count_10_min = ORM::for_table('reg_login_attempt')
->where('ip', sprintf("%u", ip2long($ip)))
->where_raw("ts > SUBTIME(NOW(),'0:10')")
->count();

if($count_hour > $limit_hour || $count_10_min > $limit_10_min){
throw new Exception('Too many login attempts!');
}
}

function rate_limit_tick($ip, $email){

// Create a new record in the login attempt table

$login_attempt = ORM::for_table('reg_login_attempt')->create();

$login_attempt->email = $email;
$login_attempt->ip = sprintf("%u", ip2long($ip));

$login_attempt->save();
}

function redirect($url){
header("Location: $url");
exit;
}

Функции rate_limit и rate_limit_tick позволяют нам ограничивать число попыток авторизации на определенный промежуток времени. Попытки авторизации записываются в базу данных reg_login_attempt. Эти функции запускаются при проведении подтверждения формы авторизации, как можно видеть в следующем фрагменте кода.

Нижеприведенный код был взят из index.php, и он отвечает за подтверждение формы авторизации. Он возвращает JSON-ответ, который управляется кодом jQuery, который мы видели в assets/js/script.js.

index.php

try{

if(!empty($_POST) && isset($_SERVER['HTTP_X_REQUESTED_WITH'])){

// Output a JSON header

header('Content-type: application/json');

// Is the email address valid?

if(!isset($_POST['email']) || !filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)){
throw new Exception('Please enter a valid email.');
}

// This will throw an exception if the person is above
// the allowed login attempt limits (see functions.php for more):
rate_limit($_SERVER['REMOTE_ADDR']);

// Record this login attempt
rate_limit_tick($_SERVER['REMOTE_ADDR'], $_POST['email']);

// Send the message to the user

$message = '';
$email = $_POST['email'];
$subject = 'Your Login Link';

if(!User::exists($email)){
$subject = "Thank You For Registering!";
$message = "Thank you for registering at our site!\n\n";
}

// Attempt to login or register the person
$user = User::loginOrRegister($_POST['email']);

$message.= "You can login from this URL:\n";
$message.= get_page_url()."?tkn=".$user->generateToken()."\n\n";

$message.= "The link is going expire automatically after 10 minutes.";

$result = send_email($fromEmail, $_POST['email'], $subject, $message);

if(!$result){
throw new Exception("There was an error sending your email. Please try again.");
}

die(json_encode(array(
'message' => 'Thank you! We\'ve sent a link to your inbox. Check your spam folder as well.'
)));
}
}
catch(Exception $e){

die(json_encode(array(
'error'=>1,
'message' => $e->getMessage()
)));
}

При успешной авторизации или регистрации, вышеприведенный код отсылает email человеку с ссылкой для авторизации. Token (лексема) становится доступной в качестве $_GET-переменной 'tkn' ввиду сгенерированного URL.

Использование ссылки авторизации запустит этот код:

index.php

if(isset($_GET['tkn'])){

// Is this a valid login token?
$user = User::findByToken($_GET['tkn']);

if($user){

// Yes! Login the user and redirect to the protected page.

$user->login();
redirect('protected.php');
}

// Invalid token. Redirect back to the login form.
redirect('index.php');
}

Запуск $user->login() создаст необходимые переменные для сессии, что позволит пользователю оставаться авторизованным при последующих входах.

Выход из системы реализуется примерно таким же образом:

Index.php

if(isset($_GET['logout'])){

$user = new User();

if($user->loggedIn()){
$user->logout();
}

redirect('index.php');
}

В конце кода мы снова перенаправляем пользователя на index.php, поэтому параметр ?logout=1 в URL исключается.

Нашему файлу index.php также потребуется защита – мы не хотим, чтобы уже авторизованные пользователи видели форму. Для этого мы используем метод $user->loggedIn():

Index.php

$user = new User();

if($user->loggedIn()){
redirect('protected.php');
}

Наконец, давайте посмотрим, как можно защитить страницу вашего сайта, и сделать ее доступной только после авторизации:

protected.php

// To protect any php page on your site, include main.php
// and create a new User object. It's that simple!

require_once 'includes/main.php';

$user = new User();

if(!$user->loggedIn()){
redirect('index.php');
}

После этой проверки вы можете быть уверены в том, что пользователь успешно авторизовался. У вас также будет доступ к данным, которые хранятся в базе данных в качестве свойств объекта $user. Чтобы вывести email пользователя и их ранг, воспользуйтесь следующим кодом:

echo 'Your email: '.$user->email;
echo 'Your rank: '.$user->rank();

Здесь rank() – это метод, так как колонка rank в базе данных обычно содержит числа (0 для обычных пользователей и 1 для администраторов), и нам нужно преобразовать это все в названия рангов, что реализуется при помощи данного метода. Чтобы преобразовать обычного пользователя в администратора, просто отредактируйте запись о пользователе в phpmyadmin (либо в любой другой программе по работе с базами данных). Будучи администратором, пользователь не будет наделен какими-то особыми возможностями. Вы сами в праве выбирать, каким правами наделять администраторов.

Готово!

На этом наша простенькая система регистрации готова! Вы можете использовать ее на уже существующем PHP-сайте, либо модернизировать ее, придерживаясь собственных требований.
Обнаружили ошибку или мёртвую ссылку?
Выделите проблемный фрагмент мышкой и нажмите CTRL+ENTER.
В появившемся окне опишите проблему и отправьте уведомление Администрации ресурса.
Нужна органическая вечная ссылка из данной статьи? Постовой?
Подробности здесь
Вам понравился материал? Поблагодарить легко!
Будем весьма признательны, если поделитесь этой статьей в социальных сетях:

Ключевые тэги: PHP, MySQL, отправные формы
Опубликовал Design FactoRy   Прочитано (раз): 41493   |   Оставлено комментариев: 4
Автор перевода — CoolWebmasters.Com ©   |   Источник материала / оригинал статьи   Распечатать
Другие статьи и новости по теме:
Комментарий #1: 21 августа 2013 @ 19:54
Написал: ITS — группа: Читатели  
На сайте с: 20.02.2010   |   Публикаций: 3   |   Комментариев: 127
ICQ: 366337851
Блин, статься очень познавательная, но вот чуточку не то...
Хотелось бы что то с использованием мыла и пароля разобрать...
А вообще круто было бы с номером телефона пример посмотреть, типа номер является логином а при регистрации на него приходит пароль...


--------------------
Вещам, которым надо бы учиться, чтобы их делать, — лучше учиться, делая их.
© Аристотель
Комментарий #2: 28 октября 2013 @ 15:24
Написал: Сереня — группа: Гости  
На сайте с: --   |   Публикаций: 0   |   Комментариев: 0
ICQ: --- не указано ---
да не пашет там ничо. где то ошибка в приложенных файлах. index.php как белый лист открывается. смысл какой глобальный в непроверенных перепечатках???))
Комментарий #3: 28 октября 2013 @ 21:33
Написал: ITS — группа: Читатели  
На сайте с: 20.02.2010   |   Публикаций: 3   |   Комментариев: 127
ICQ: 366337851
Сереня, ну так разбирать надо всё...


--------------------
Вещам, которым надо бы учиться, чтобы их делать, — лучше учиться, делая их.
© Аристотель
Комментарий #4: 28 октября 2013 @ 22:36
Написал: Сереня — группа: Гости  
На сайте с: --   |   Публикаций: 0   |   Комментариев: 0
ICQ: --- не указано ---
загадочная русская душа?)))) что разбирать? я верстальщик! пойду погуглу еще чтонить блоее понятное))))
Добавление комментария
Уважаемые пользователи!
При добавлении комментариев на сайт Вам следует учитывать следующее - все комментарии проверяются Администрацией на предмет отсутствия спама. При обнаружении признаков спама, в оставленном Вами комментарии, сам комментарий будет незамедлительно удалён, а Ваш IP-адрес будет забанен без предупреждения! Учётные записи пользователей, рассылающих спам, блокируются/удаляются без права последующего восстановления.

С уважением, Администрация сайта.
* = поля обязательны к заполнению
Полужирный Наклонный текст Подчеркнутый текст Зачеркнутый текст | Выравнивание по левому краю По центру Выравнивание по правому краю | Вставка смайликов Выбор цвета | Скрытый текст Вставка цитаты Преобразовать выбранный текст из транслитерации в кириллицу Вставка спойлера
Вопрос : Назовите месяц November по-русски
Подтверждение кода безопасности :

Включите эту картинку для отображения кода безопасности
обновить, если не виден код


Популярные публикации


















Свежие шаблоны сайтов каждый день
С миру по нитке
«    Июль 2017    »
ПнВтСрЧтПтСбВс
 12
3456789
10111213141516
17181920212223
24252627282930
31