Чому небезпечно містити параметр PHP register_globals? Створення простої системи реєстрації користувачів на PHP і MySQL index php register

Вітаю! Зараз ми спробуємо реалізувати найпростішу реєстрацію на сайті за допомогою PHP+MySQL. Для цього на вашому комп'ютері потрібно встановити Apache. Нижче наведено принцип роботи нашого скрипта.

1. Почнемо зі створення таблички users у базі . Вона міститиме дані користувача (логін та пароль). Зайдемо в phpmyadmin (якщо ви створюєте базу на своєму ПК http://localhost/phpmyadmin/). Створюємо таблицю users, у ній буде 3 поля.

Я створюю її в базі mysql, ви можете створювати в іншій базі. Далі встановлюємо значення, як у малюнку:

2. Необхідне з'єднання з цією таблицею. Давайте створимо файл bd.php. Його зміст:

У моєму випадку це виглядає так:

Зберігаємо bd.php.
Чудово! Ми маємо таблицю в базі, з'єднання до неї. Тепер можна приступати до створення сторінки, на якій користувачі залишатимуть свої дані.

3. Створюємо файл reg.php із змістом (усі коментарі всередині):



Реєстрація


Реєстрація


Ваш логін:




Ваш пароль:








4. Створюємо файл, який заноситиме дані в базу і зберігатиме користувача. save_user.php (коментарі всередині):

5. Тепер наші користувачі можуть реєструватися! Далі необхідно зробити "двері" для входу на сайт вже зареєстрованим користувачам. index.php (коментарі всередині):




Головна сторінка


Головна сторінка


Ваш логін:


Ваш пароль:






Зареєструватись



Ну от і все! Може урок і нудний, але дуже корисний. Тут показано лише ідею реєстрації, далі Ви можете вдосконалити її: додати захист, оформлення, поля з даними, завантаження аватарів, вихід з акаунту (для цього просто знищити змінні з сесії функцією unset) і так далі. Успіхів!

Все перевірив, чи працює справно!

Reg.ru: домени та хостинг

Найбільший реєстратор та хостинг-провайдер у Росії.

Понад 2 мільйони доменних імен на обслуговуванні.

Просування, пошта для домену, рішення для бізнесу.

Понад 700 тис. клієнтів у всьому світі вже зробили свій вибір.

*Наведіть курсор миші, щоб призупинити прокручування.

Назад вперед

Створення простої системи реєстрації користувачів на PHP та MySQL

Створення системи реєстрації – це велика робота. Вам доводиться писати код, який здійснює валідацію email-адрес, відправляє повідомлення на пошту з підтвердженням реєстрації, а також здійснює валідацію решти полів форми та багато ще всього.

І навіть після того, як ви все це напишіть, користувачі будуть реєструватися неохоче, т.к. це вимагає певних зусиль з боку.

У цьому уроці ми створимо дуже просту систему реєстрації, яка не вимагає і не зберігає паролів взагалі! Результат буде легко змінювати та додати до вже існуючого PHP-сайту. Бажаєте з'ясувати, як це працює? Читайте нижче.



Ось як наша супер проста система працюватиме:

Ми скомбінуємо форму авторизації та реєстрацію. У цій формі буде поле для введення email-адреси та кнопка реєстрації;
- При заповненні поля email-адресою, після натискання на кнопку реєстрації буде створено запис про нового користувача, але тільки в тому випадку, якщо введена email-адреса не була знайдена в базі даних.

Після цього створюється випадковий унікальний набір символів (токен), який відправляється на вказану користувачем пошту у вигляді посилання, яка буде актуальна протягом 10 хвилин;
– За посиланням користувач переходить на наш сайт. Система визначає наявність токена та авторизує користувача;

Переваги такого підходу:

Не потрібно зберігати паролі та здійснювати валідацію полів;
- немає необхідності у відновленні пароля, секретних питань тощо;
- З моменту, як користувач зареєструвався/авторизувався, ви можете завжди бути впевнені, що цей користувач буде у вашій зоні доступу (що email-адреса є істинною);
- неймовірно простий процес реєстрації;

Недоліки:

Безпека облікового запису користувача. Якщо хтось має доступ до пошти користувача, він може авторизуватись.
- Email не захищений і може бути перехоплений. Майте на увазі, що це питання є актуальним і у випадку, коли пароль був забутий і його необхідно відновити, або в будь-якій системі авторизації, яка не використовує HTTPS для передачі даних (логін/пароль);
- Поки ви налаштуєте як потрібно поштовий сервер, існує шанс, що повідомлення з посиланнями на авторизацію потраплятимуть до спаму;

Порівнюючи переваги та недоліки нашої системи, можна сказати, що система має високе юзабіліті (максимально зручна для кінцевого користувача) і водночас має невисокий показник безпеки.

Тож використовувати її пропонується для реєстрацій на форумах та сервісах, які не працюють із важливою інформацією.

Як користуватись цією системою

У випадку, коли вам потрібно просто використовувати систему для авторизації користувачів на вашому сайті, і вам не хочеться розбирати цей урок по кісточках, ось що вам потрібно зробити:

Вам потрібно завантажити вихідні джерела, додані до уроку
- В архіві знайти файл tables.sql Імпортуйте його у вашу базу даних, використовуючи опцію імпорту в phpMyAdmin. Альтернативний спосіб: відкрити цей файл через текстовий редактор, скопіювати SQL запит та виконати його;
- Відкрити includes/main.php та заповнити налаштування зв'язку з вашою базою даних (вказати користувача та пароль для зв'язку з базою, а також хост та ім'я бази). У цьому ж файлі, ви також повинні вказати email, який буде використаний як оригінальна адреса для повідомлень, що відправляються системою. Деякі хости блокують вихідні мейли поки у формі не буде вказана справжня адреса електронної пошти, яка була створена з панелі управління хостом, так що вкажіть реальну адресу;
- Завантажте всі файли index.php, protected.php та папки assets та includes через FTP на ваш хост;
- Додати код нижче на кожну PHP-сторінку, де потрібно відобразити форму авторизації;

Require_once "includes/main.php"; $user = новий User(); if(!$user->loggedIn())( redirect("index.php"); )
– Готово!

Для тих, кому цікаво, як це все працює - вперед до читання нижче!

Перший крок – написання HTM-коду форми авторизації. Цей код розміщується у файлі index.php. Цей файл також містить PHP-код, який обробляє дані форми та інші корисні функції системи авторизації. Дізнатися про це можна у розділі нижче, присвяченому огляду PHP коду.

index.php

Tutorial: Super Simple Registration System з PHP & MySQL Login or Register

Enter your email address above and we will send
you a login link.

Login / Register

У головній секції (між тегами та ) я підключив основні стилі (у цьому уроці вони не розуміються, тому ви можете подивитися їх самі. Папка assets/css/style.css). До тега, що закриває, я підключив бібліотеку jQuery і файл script.js, який ми напишемо і розберемо трохи нижче.


JavaScript

jQuery відстежує стан кнопки "Зареєструватися/авторизуватися" за допомогою функції e.preventDefault()та надсилає AJAX-запити. Залежно від відповіді сервера, виводить те чи інше повідомлення та визначає подальші дії/

assets/js/script.js

$(function()( var form = $("#login-register"); form.on("submit", function(e)( if(form.is(".loading, .loggedIn"))) ; ) var email = form.find("input").val(), messageHolder = form.find("span");e.preventDefault(); (m)( if(m.error)( form.addClass("error"); messageHolder.text(m.message); ) else( form.removeClass("error").addClass("loggedIn"); messageHolder). $(document).ajaxStart(function()( form.addClass("loading"); )); $(document).ajaxComplete(function()( form. text(m.message); ) )); )); removeClass("loading"); )); ));

був доданий у форму для відображення поточного стану AJAX-запиту (це стало можливим завдяки методам ajaxStart()) та ajaxComplete(), які ви зможете знайти ближче до кінця файлу).

Цей клас показує анімований gif-файл, що крутиться (як би натякає нам на те, що запит обробляється), і також виступає як прапор, що запобігає повторному відправленню форми (коли кнопка зареєструватися була вже одного разу натиснута). Клас .loggedIn - це інший прапор - встановлюється тоді, коли був відправлений email. Цей прапор моментально блокує будь-які подальші дії з формою.

Схема бази даних

Наша неймовірно проста система реєстрації використовує 2 MySQL таблиці (SQL-код знаходиться у файлі tables.sql). Перша зберігає дані про облікові записи користувачів. Друга зберігає інформацію про кількість спроб входу.


Схема таблиці користувачів.

Система не використовує паролі, що видно на схемі. На ній можна побачити колонку token з токенами, що сусідить з колонкою token_validity . Токен встановлюється як тільки користувач підключається до системи, задає свій email для відправки повідомлення (докладніше про це в наступному блоці). Колонка token_validity встановлює час на 10 хвилин пізніше, після якого токен перестає бути актуальним.


Схема таблиці, яка рахує кількість спроб авторизації.

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

Тепер ми можемо написати трохи PHP-коду. Основний функціонал системи покладено клас User.class.php , який ви можете бачити нижче.

Цей клас активно використовує idorm (docs), ці бібліотеки є мінімально необхідними інструментами для роботи з базами даних. Він обробляє доступ до бази даних, генерацію токенів та їх валідацію. Він є простим інтерфейсом, що дозволяє легко підключити систему реєстрації до вашого сайту, якщо він використовує PHP.

User.class.php

Class User( // Приватний ORM випадок private $orm; /** * Знайти користувача по токену. Тільки валідні токени, прийняті до розгляду. Токен генерується тільки на 10 хвилин з того моменту, як був створений * @param string $token. Це шуканий токен * @return User. Повернути значення функції User */ public static function findByToken($token)( // знайти токен в базі і переконатися, що встановлений коректний часовий штамп $result = ORM::for_table("reg_users") ->where ("token", $token) ->where_raw("token_validity > NOW()") ->find_one(); if(!$result)( return false; ) return new User($result); ) /** * Авторизувати або зареєструвати користувача * @param string $email Користувацька email-адреса * @return User */ public static function loginOrRegister($email)( // Якщо такий користувач вже існує, повернути значення функції User від заданої email-адреси, що зберігається в базі if(User::exists($email))( return new User($email); ) // Інакше створити нового користувача в базі і повернути значення функції User::create від вказаного email return User::create($email ); ) /** * Створити нового користувача та зберегти в базу * @param string $email. Користувацька email-адреса * @return User */ private static function create($email)( // Записати нового користувача і повернути результат функції User від цих значень $result = ORM::for_table("reg_users")->create(); $result->email = $email;$result->save(); Користувацька email-адреса * @return boolean */ public static function exists($email)( // Чи існує користувач у базі? $result = ORM::for_table("reg_users") ->where("email", $email) ->count(); return $result == 1; ) /** * Створити новий об'єкт користувача * @param екземпляр $param ORM , id, email or 0 * @return User */ public function __construct($param = null) ( if($param instanceof ORM)( // ORM перевірка пройдена $this->orm = $param; ) else if(is_string($param))( // Перевірка на email пройдена $this->orm = ORM::for_table ("reg_users") ->where("email", $param) ->find_one(); ) else( $id = 0; if(is_numeric($param)))( // ідентифікатору користувача передається значення змінної $param $id = $param; ) else if(isset($_SESSION["loginid"]))) // В іншому випадку дивись сесію $id = $_SESSION["loginid"]; ) $this->orm = ORM::for_table( "reg_users") ->where("id", $id) ->find_one(); ) ) /** * Сгенерувати новий SHA1 токен авторизації, записує в базу і повертає його значення * @return string */ public function generateToken( )( // Згенерувати токен для авторизованого користувача та зберегти його в базу $token = sha1($this->email.time().rand(0, 1000000)); // Зберегти токен в основі // І помітити його, що він актуальний лише протягом 10 наступних хвилин $this->orm->set("token", $token); $this->orm->set_expr("token_validity", "ADDTIME(NOW(),"0:10")"); $this->orm->save(); return $token; ) /** * Авторизувати користувача * @return void */ public function login()( // Позначити користувача, як авторизованого $_SESSION["loginid"] = $this->orm->id; // Оновити значення поля бази last_login $this->orm->set_expr("last_login", "NOW()"); $this->orm->save(); ) /** * Знищити сесію та розлогінити користувача ()( $_SESSION = array(); unset($_SESSION); ) /** * Перевірка, чи заходив користувач * @return boolean */ public function loggedIn()( return isset($this->orm->id) && $_SESSION["loginid"] == $this->orm->id; ) /** * Перевірка чи є користувач адміністратором * @return boolean */ public function isAdmin()( return $this->rank() = = "administrator"; ) /** * Знайти тип користувача, може бути або administrator або regular * @return string */ public function rank()( if($this->orm->rank == 1)( return "administrator "; ) return "regular"; ) /** * Метод дозволяє отримати приватну інформацію користувача в якості властивостей об'єкта User * @param string $key Ім'я властивості, що отримує доступ * @return mixed */ public function __get($key)( if(isset($this->orm->$key))( return $this->orm->$key; ) return null; )

Токени генеруються за допомогою алгоритму SHA1 і зберігаються в базі даних. Я використовую функції часу MySQL, щоб встановити 10-хвилинне обмеження актуальності токена.

Коли токен проходить процедуру валідації, ми прямо говоримо обробнику, що ми розглядаємо тільки токени, які ще не закінчилися термін придатності, що зберігається в стовпці token_validity.

Зверніть увагу, що я використовую магічний метод __getбібліотеки docs наприкінці файлу, щоб перехопити доступ до властивостей об'єкта User.

Завдяки цьому стає можливим отримати доступ до інформації, що зберігається в базі, завдяки властивостям $user->email, $user->token та ін. У наступному фрагменті коду розглянемо для прикладу використання цих класів.


Захищена сторінка

Ще один файл, що зберігає корисний та необхідний функціонал - це файл functions.php. Тут є кілька так званих хелперів - функцій-помічників, які дозволяють створювати чистіший і читабельніший код в інших файлах.

functions.php

Function send_email($from, $to, $subject, $message)( // Хелпер, що відправляє email $headers = "MIME-Version: 1.0" . "\r\n"; $headers .= "Content-type: text /plain; charset=utf-8" . "\r\n"; $headers .= "Від: ".$from . "\r\n"; return mail($to, $subject, $message, $headers ); ) function get_page_url()( // Визначити URL PHP-файлу $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)( // Кількість спроб входу за останню годину за цією IP-адресою $count_hour = ORM: :for_table("reg_login_attempt") ->where("ip", sprintf("%u", ip2long($ip))) ->where_raw("ts > SUBTIME(NOW(),"1:00")") ->count(); // Кількість спроб входу за останні 10 хвилин за цією IP-адресою $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"); кількість спроб входу $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"); // Чи є ця email-адреса валідним if(!isset($_POST["email"]) || !filter_var($_POST["email"], FILTER_VALIDATE_EMAIL))( throw new Exception("Please enter a valid email."); ) // Перевірка. Чи дозволено користувачеві авторизуватися, чи не перевищив він кількість допустимих підключень?(файл functions.php для більшої інформації) rate_limit($_SERVER["REMOTE_ADDR"]); // Записати цю спробу авторизації rate_limit_tick($_SERVER["REMOTE_ADDR" _POST["email"]); // Надіслати лист користувачеві $message = ""; $email = $_POST["email"]; $subject = "Your Login Link"; )( $subject = "Thank You For Registering!"; $message = "Thank you for registering at our site!\n\n"; ) // Спроба авторизувати або зареєструвати користувача $user = User::loginOrRegister($_POST[ "email"]); $message.= get_page_url()."?tkn=".$user->generateToken()."\n\n"; $message.= "Отправляється expire автоматично після 10 хвилин."; $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 .) catch(Exception $e)( die(json_encode(array("error"=>1, "message" => $e->getMessage() )));

Після успішної авторизації/реєстрації код вище надішле користувачеві посилання для авторизації. Токен стає доступним, т.к. він передається як змінна в генерованому засланні методом $_GETз маркером tkn

index.php

If(isset($_GET["tkn"]))( // Чи є цей токен валідним для авторизації? $user = User::findByToken($_GET["tkn"]); if($user)( // Так , є. Здійснити редирект на захищену сторінку $user->login(); redirect("protected.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 = новий User(); if($user->loggedIn())( redirect("protected.php"); )

Нарешті, ось шмат коду, що дозволяє захистити сторінки вашого сайту і зробити її доступною тільки після авторизації.

protected.php

// Щоб захистити кожну сторінку на вашому сайті, підключіть до неї файл // main.php і створіть новий об'єкт User. Ось як це просто! require_once "includes/main.php"; $user = новий User(); if(!$user->loggedIn())( redirect("index.php"); )

Після цієї перевірки ви можете бути впевнені, що користувач був успішно авторизований. Ви також можете отримати доступ до інформації, що зберігається в базі за допомогою властивостей об'єкта $user. Для виведення emailу користувача та його статусу використовуйте цей код:

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

Метод rank()використовується тут тому що в базі зазвичай зберігаються номери (0 для звичайного користувача, 1 для адміністратора) і нам потрібно перетворити ці дані на статуси, до яких вони належать, у чому нам і допомагає цей метод.

Щоб зробити з звичайного користувача адміністратора, просто відредагуйте запис користувача через phpMyAdmin (або будь-яку іншу програму, що дозволяє керувати базами даних). Статус адміністратора не дає жодних привілеїв, в даному прикладі на сторінці буде виведено, що ви адміністратор – і все.

А ось що з цим робити - залишається вже на ваш розсуд, ви можете самі написати і скласти код, який задає певні привілеї та можливості для адміністраторів.

Ми закінчили!

З цією неймовірно супер квазі простою формою ми закінчили! Ви можете використовувати її у ваших PHP-сайтах, це досить просто. Також ви можете модифікувати її під себе та зробити її такою, як ви хочете.

Матеріал підготував Денис Малишок спеціально для сайту сайт

P.S. Хочете рухатися далі в освоєнні PHP та ОВП? Зверніть увагу на преміум-уроки з різних аспектів сайтобудування, включаючи програмування на PHP, а також на безкоштовний курс створення своєї CMS-системи на PHP з нуля з використанням ООП:

Сподобався матеріал і хочете віддячити?
Просто поділіться з друзями та колегами!


У зв'язку з тим, що дуже часто виникають питання щодо глобальних змінних та проблем, пов'язаних із відключенням директиви register_globals, спробуємо трохи розкрити цю тему в цій статті.

Спочатку визначимо, що таке зовнішні змінні. Це будь-які змінні, які вступають у програму ззовні, тобто. не визначено у самій програмі. Для скрипту на php усі змінні, що передаються через рядок браузера або через форму є зовнішніми.
Розглянемо, як вони створюються.

Якщо на сервері включена директива register_globals = On (у php.ini), то під час передачі змінних через форму або через рядок браузера, у скрипті, якому ці змінні призначені, вони будуть створені автоматично. Тобто. якщо у вас у рядку браузера написано: www.server.ru/index.php?var=1, то в скрипті index.php буде автоматично створена змінна $var зі значенням 1.

Зауваження

Вказана директива є одним із найбільш дискусійних моментів у мові PHP. З одного боку, її використання справді може породити реальні проблеми із захистом PHP-сценаріїв, при неналежному обліку можливих помилкових ситуацій і багато розробників справедливо зазначають, що написання скриптів без використання глобальних змінних на 90% зменшує вразливість скриптів до різноманітних атак. З іншого боку, на початку виникнення PHP, не одна тисяча користувачів довірилася розробникам мови (до версії PHP 4.3 ця директива була за замовчуванням включена), в силу чого в даний час є мільйони скриптів, що реально функціонують, написаних з використанням глобальних змінних (Варто відзначити, що в навчальних цілях іноді зовсім не зайве писати скрипти з використанням глобальних змінних, оскільки із заміна суперглобальні масиви сильно погіршує читабельність коду).

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

При відключеній директиві register_globals доступ до таких змінних можливий двома способами:

  • через асоціативні масиви HTTP_***_VARS (HTTP_POST_VARS тощо)
  • через суперглобальні масиви ($_ENV, $_GET, $_POST, $_SERVER, $_COOKIE, $_FILES та ін.)

Суперглобальні масиви доступні у будь-якій області видимості. Розробники PHP рекомендують відключати на сервері директиву register_globals та працювати зі змінними через суперглобальні масиви. Ця рекомендація пов'язана з проблемами безпеки, які могли б виникнути при включеній директиві register_globals.

Хоча донедавна на хостингах директива register_globals залишалася включеною. Ситуація почала змінюватися з виходом PHP 5, де ця директива за замовчуванням вимкнена і хостери не поспішають її вмикати (можливо і правильно).

Отже, що саме зробити щоб отримати змінні - треба взяти їх із суперглобальних масивів. Наприклад, для отримання змінних, переданих через рядок браузера використовують масив $_GET. Допустимо, у рядку браузера написано www.server.ru/index.php?var=1, Тоді для отримання змінної var в index.php потрібно написати:

$var=$_GET["var"];

А, наприклад, для отримання змінних переданих із форми методом POST у скрипті-обробнику форми потрібно написати:

$var=$_POST["var"];

У цій статті ви дізнаєтесь, як створити форму реєстрації та авторизації, використовуючи HTML, JavaScript, PHP та MySql. Такі форми використовуються майже на кожному сайті незалежно від його типу. Вони створюються і для форуму, і для інтернету магазину і для соціальних мереж (такі як Facebook, Twiter, Odnoklassniki) і для багатьох інших типів сайтів.

Якщо у Вас сайт на локальному комп'ютері, то я сподіваюся, що у Вас вже встановлено та запущено локальний сервер. Без нього нічого не працюватиме.

Створення таблиці в базі даних

Для того, щоб реалізувати реєстрацію користувачів, в першу чергу нам потрібна База даних. Якщо вона вже є, то чудово, інакше, Вам потрібно її створювати. У статті я докладно пояснюю, як зробити це.

І так, у нас є База Даних (скорочено БД), тепер нам потрібно створити таблицю usersв якій додаватимемо наших зареєстрованих користувачів.

Як створювати таблицю у БД, я також пояснив у статті . Перед тим як створити таблицю, нам необхідно визначити, які поля вона міститиме. Ці поля відповідатимуть полям із форми реєстрації.

Значить, подумали, представили, які поля будуть у нашої форми і створюємо таблицю usersз такими полями:

  • id- Ідентифікатор. Поле idмає бути у кожної таблиці з БД.
  • first_name- Для збереження імені.
  • last_name- Для збереження прізвища.
  • email- Для збереження поштової адреси. E-mail ми будемо використовувати як логін, тому це поле має бути унікальним, тобто мати індекс UNIQUE.
  • email_status- Поле для вказівки, чи підтверджено пошту чи ні. Якщо пошта підтверджена, воно матиме значення 1, інакше значення 0.
  • password- Для збереження пароля.


Якщо Ви хочете, щоб Ваша форма реєстрації мала ще якісь поля, Ви можете їх тут також додати.

Все, наша таблиця usersготова. Переходимо до наступного етапу.

Підключення до бази даних

Базу даних ми створили, тепер потрібно до неї підключитися. Підключення будемо здійснювати за допомогою PHP розширення MySQLi.

У папці нашого сайту створюємо файл з ім'ям dbconnect.php, і в ньому пишемо наступний скрипт:

Цей файл dbconnect.phpнеобхідно буде підключити до обробників форм.

Зверніть увагу на змінну $address_site, тут я вказав назву мого тестового сайту, над яким працюватиму. Ви відповідно вкажіть назву Вашого сайту.

Структура сайту

Тепер розберемося з HTML структурою нашого сайту.

Шапку та підвал сайту винесемо в окремі файли, header.phpі footer.php. Їх будемо підключати на всіх сторінках. А саме на головній (файл index.php), на сторінку з формою реєстрації (файл form_register.php) та на сторінку з формою авторизації (файл form_auth.php).

Блок із нашими посиланнями, реєстраціяі авторизація, додамо до шапки сайту, щоб вони відображалися на всіх сторінках. Одне посилання буде ввести на сторінку з формою реєстрації (файл form_register.php) а інша на сторінку з формою авторизації (файл form_auth.php).

Вміст файлу header.php:

Назва нашого сайту

Зрештою, головна сторінка, у нас виглядає так:


Звичайно, у Вас на сайті може бути зовсім інша структура, але це зараз для нас не важливо. Головне, щоб були посилання (кнопки) реєстрації та авторизації.

Тепер перейдемо до форми реєстрації. Як Ви вже зрозуміли, вона у нас знаходиться у файлі form_register.php.

Ідемо до Бази Даних (у phpMyAdmin), відкриваємо структуру таблиці usersі дивимось які поля нам потрібні. Отже, нам потрібні поля для введення імені та прізвища, поле для введення поштової адреси (Email) та поле для введення пароля. І ще з метою безпеки додамо поле для введення капчі.

На сервері, в результаті обробки форми реєстрації можуть виникнути різні помилки, через які користувач не зможе зареєструватися. Тому для того, щоб користувач розумів чому не проходить реєстрація, необхідно вивести йому повідомлення про ці помилки.

Перед виведенням форми додаємо блок для виведення повідомлень про помилки із сесії.

І ще момент, якщо користувач вже авторизований, і він заради інтересу заходить на сторінку реєстрації безпосередньо, написавши в адресний рядок браузера адреса сайту/form_register.php, то ми в цьому випадку замість форми реєстрації виведемо йому заголовок про те, що він вже зареєстрований.

Загалом код файлу form_register.phpу нас вийшов таким:

Ви вже зареєстровані

У браузері сторінка з формою реєстрації виглядає так:


За допомогою атрибуту required ми зробили всі поля обов'язковими до заповнення.

Зверніть увагу на код форми реєстрації де виводиться капча:


Ми маємо значення атрибута src для зображення, вказали шлях до файлу captcha.php, що генерує дану капчу.

Подивимося на код файлу captcha.php:

Код добре закоментований, тому я зупинюся лише на одному моменті.

Усередині функції imageTtfText(), вказано шлях до шрифту verdana.ttf. Так ось для коректної роботи капчі, ми маємо створити папку fonts, і помістити туди файл шрифту verdana.ttf. Його Ви можете знайти та скачати з інтернету, або взяти з архіву з матеріалами цієї статті.

З HTML структурою ми закінчили, настав час рухатися далі.

Перевірка email на валідність за допомогою jQuery

Будь-яка форма потребує перевірки на валідність введених даних як на стороні клієнта (за допомогою JavaScript, jQuery), так і на стороні сервера.

Особливу увагу ми повинні приділити полю Email. Дуже важливо, щоб введена поштова адреса була валідною.

Для даного поля input ми задали тип email (type="email"), це нас трошки застерігає від неправильних форматів. Але цього недостатньо, тому що через інспектор коду, якого надає нам браузер, можна легко змінити значення атрибуту typeз emailна text, і все, наша перевірка буде вже недійсною.


І в такому разі, ми маємо зробити більш надійну перевірку. Для цього скористаємося бібліотекою jQuery від JavaScript.

Для підключення бібліотеки jQuery у файлі header.phpміж тегами , перед закриває тега , додаємо цей рядок:

Відразу після цього рядка додамо код перевірки валідації email. Тут додамо код перевірки довжини введеного пароля. Його довжина має бути не менше 6 символів.

За допомогою цього скрипту ми перевіряємо введену поштову адресу на валідність. Якщо користувач ввів неправильний Email, ми виводимо йому помилку про це і дезактивуємо кнопку відправки форми. Якщо все добре, то ми прибираємо помилку та активуємо кнопку відправлення форми.

І так, із перевіркою форми на клієнтській частині ми закінчили. Тепер ми можемо відправити її на сервер, де також зробимо пару перевірок та додамо дані до БД.

Реєстрація користувача

Форму ми надсилаємо на обробку файлу register.phpчерез метод POST. Назва файлу обробника, вказано в значення атрибута action. А метод відправлення вказано у значення атрибуту метод.

Відкриваємо цей файл register.phpі перше, що нам потрібно зробити, це написати функцію запуску сесії та підключити створений нами раніше файл dbconnect.php(У цьому файлі ми зробили підключення до БД). І ще, відразу оголосимо осередки error_messagesі success_messagesу глобальному масиві сесії. У error_mesagesбудемо записувати всі повідомлення про помилки, що виникають при обробці форми, а в succes_messages, будемо записувати радісні повідомлення.

Перед тим, як продовжити, ми повинні перевірити, чи взагалі була відправлена ​​форма . Зловмисник може подивитися на значення атрибуту actionз форми, і дізнатися який файл займається обробкою цієї форми. І йому може спасти на думку перейти безпосередньо в цей файл, набираючи в адресному рядку браузера таку адресу: http://арес_сайту/register.php

Тому нам потрібно перевірити наявність осередку у глобальному масиві POST, ім'я якого відповідає імені нашої кнопки "Зареєструватися" з форми. Таким чином ми перевіряємо чи була натиснута кнопка "Зареєструватися" чи ні.

Якщо зловмисник спробує перейти безпосередньо до цього файлу, він отримує повідомлення про помилку. Нагадую, що змінна $address_site містить назву сайту і вона була оголошена у файлі dbconnect.php.

Значення капчі в сесії було додано під час її генерації, у файлі captcha.php. Для нагадування ще раз покажу цей шматок коду з файлу captcha.php, де додається значення капчі в сесію:

Тепер приступимо до самої перевірки. У файлі register.php, всередині блоку if, де перевіряємо, чи була натиснута кнопка "Зареєструватися", а точніше де вказано коментар " // (1) Місце для наступного шматка кодупишемо:

//Перевіряємо отриману капчу //Обрізаємо прогалини з початку та з кінця рядка $captcha = trim($_POST["captcha"]); if(isset($_POST["captcha"]) && !empty($captcha))( // Порівнюємо отримане значення зі значенням із сесії. if(($_SESSION["rand"] != $captcha) && ($_SESSION ["rand"] != ""))( // Якщо капча не вірна, то повертаємо користувача на сторінку реєстрації, і там виведемо йому повідомлення про помилку, що він ввів неправильну капчу. $error_message = "

Помилка! Ви ввели неправильну капчу

// Зберігаємо в сесію повідомлення про помилку. $_SESSION["error_messages"] = $error_message; //Повертаємо користувача на сторінку реєстрації header("HTTP/1.1 301 Moved Permanently"); ."/form_register.php"); //Зупиняємо скрипт exit(); ) // (2) Місце для наступного шматка коду )else( //Якщо капча не передана або воно є порожнім exit("

Помилка! Відсутній код перевірки, тобто код капчі. Ви можете перейти на головну сторінку.

"); }

Далі нам потрібно обробляти отримані дані з масиву POST. Насамперед, нам потрібно перевірити вміст глобального масиву POST, тобто чи є там осередки, імена яких відповідають іменам полів input з нашої форми.

Якщо осередок існує, то обрізаємо прогалини з початку і з кінця рядка з цього осередку, інакше перенаправляємо користувача назад на сторінку з формою реєстрації.

Далі, після того як обрізали пробіли, додаємо рядок у змінну та перевіряємо цю змінну на порожнечу, якщо вона не є порожньою, то йдемо далі, інакше перенаправляємо користувача назад на сторінку з формою реєстрації.

Цей код вставляємо у вказане місце " // (2) Місце для наступного шматка коду".

/* Перевіряємо якщо в глобальному масиві $_POST існують дані відправлені з форми і укладаємо передані дані в звичайні змінні. = trim($_POST["first_name"]); // Перевіряємо змінну на порожнечу if(!empty($first_name))( // Для безпеки, перетворюємо спеціальні символи в HTML-сутності $first_name = htmlspecialchars($first_name, ENT_QUOTES) ; )else( // Зберігаємо в сесію повідомлення про помилку. $_SESSION["error_messages"] .= "

Вкажіть Ваше ім'я

Немає поля з ім'ям

// Повертаємо користувача на сторінку реєстрації header("HTTP/1.1 301 Moved Permanently"); header("Location: ".$address_site."/form_register.php"); //Зупиняємо скрипт exit(); ) if( isset($_POST["last_name"]))( // Обрізаємо прогалини з початку і з кінця рядка $last_name = trim($_POST["last_name"]); if(!empty($last_name))( // Для безпеки , перетворимо спеціальні символи в HTML-сутності $last_name = htmlspecialchars($last_name, ENT_QUOTES); )else( // Зберігаємо в сесію повідомлення про помилку. $_SESSION["error_messages"] .= "

Вкажіть Ваше прізвище

// Повертаємо користувача на сторінку реєстрації header("HTTP/1.1 301 Moved Permanently"); header("Location: ".$address_site."/form_register.php"); //Зупиняємо скрипт exit(); ) )else ( // Зберігаємо в сесію повідомлення про помилку. $_SESSION["error_messages"] .= "

Немає поля з прізвищем

// Повертаємо користувача на сторінку реєстрації header("HTTP/1.1 301 Moved Permanently"); header("Location: ".$address_site."/form_register.php"); //Зупиняємо скрипт exit(); ) if( isset($_POST["email"]))( //Обрізаємо прогалини з початку і з кінця рядка $email = trim($_POST["email"]); if(!empty($email))( $email = htmlspecialchars ($email, ENT_QUOTES);// (3) Місце коду для перевірки формату поштової адреси та його унікальності )else( // Зберігаємо в сесію повідомлення про помилку. $_SESSION["error_messages"] .= "

Вкажіть Ваш email

// Повертаємо користувача на сторінку реєстрації header("HTTP/1.1 301 Moved Permanently"); header("Location: ".$address_site."/form_register.php"); //Зупиняємо скрипт exit(); ) )else ( // Зберігаємо в сесію повідомлення про помилку. $_SESSION["error_messages"] .= "

// Повертаємо користувача на сторінку реєстрації header("HTTP/1.1 301 Moved Permanently"); header("Location: ".$address_site."/form_register.php"); //Зупиняємо скрипт exit(); ) if( isset($_POST["password"]))( //Обрізаємо прогалини з початку і з кінця рядка $password = trim($_POST["password"]); if(!empty($password))( $password = htmlspecialchars ($password, ENT_QUOTES); //Шифруємо папроль $password = md5($password."top_secret"); )else( // Зберігаємо в сесію повідомлення про помилку. $_SESSION["error_messages"] .= "

Вкажіть Ваш пароль

// Повертаємо користувача на сторінку реєстрації header("HTTP/1.1 301 Moved Permanently"); header("Location: ".$address_site."/form_register.php"); //Зупиняємо скрипт exit(); ) )else ( // Зберігаємо в сесію повідомлення про помилку. $_SESSION["error_messages"] .= "

// Повертаємо користувача на сторінку реєстрації header("HTTP/1.1 301 Moved Permanently"); header("Location: ".$address_site."/form_register.php"); //Зупиняємо скрипт exit(); ) // (4) Місце для коду додавання користувача до БД

Особливу важливість має поле email. Ми повинні перевірити формат отриманої поштової адреси та її унікальність у БД. Тобто чи не зареєстрований вже якийсь користувач із такою самою поштовою адресою.

У вказаному місці // (3) Місце коду для перевірки формату поштової адреси та її унікальності" додаємо наступний код:

//Перевіряємо формат отриманої поштової адреси за допомогою регулярного вираження $reg_email = "/^**@(+(*+)*\.)++/i"; //Якщо формат отриманої поштової адреси не відповідає регулярному виразу if(!preg_match($reg_email, $email))( // Зберігаємо в сесію повідомлення про помилку. $_SESSION["error_messages"] .= "

Ви ввели неправильний email

// Повертаємо користувача на сторінку реєстрації header("HTTP/1.1 301 Moved Permanently"); header("Location: ".$address_site."/form_register.php"); //Зупиняємо скрипт exit(); ) // Перевіряємо, чи немає вже такої адреси в БД $result_query = $mysqli->query("SELECT `email` FROM `users` WHERE `email`="".$email."""); //Якщо отриманих рядків рівно одиниці, значить користувач з такою поштовою адресою вже зареєстрований if($result_query->num_rows == 1)( //Якщо отриманий результат не дорівнює false if(($row = $result_query->fetch_assoc()) != false) ( // Зберігаємо в сесію повідомлення про помилку. $_SESSION["error_messages"] .= "

Користувач із такою поштовою адресою вже зареєстрований

// Повертаємо користувача на сторінку реєстрації header("HTTP/1.1 301 Moved Permanently"); header("Location: ".$address_site."/form_register.php"); )else( // Зберігаємо в сесію повідомлення про помилку $_SESSION["error_messages"] .= "

Помилка у запиті до БД

// Повертаємо користувача на сторінку реєстрації header("HTTP/1.1 301 Moved Permanently"); header("Location: ".$address_site."/form_register.php"); ) /* закриття вибірки */ $result_query-> close(); //Зупиняємо скрипт exit(); ) /* закриття вибірки */ $result_query->close();

І так, ми закінчили з усіма перевірками, настав час додати користувача в БД. У вказаному місці // (4) Місце для коду додавання користувача до БД" додаємо наступний код:

//Запит на додавання користувача до БД $result_query_insert = $mysqli->query("INSERT INTO `users` (first_name, last_name, email, password) VALUES ("".$first_name."", "".$last_name." ", "".$email."", "".$password."")"); if(!$result_query_insert)( // Зберігаємо в сесію повідомлення про помилку. $_SESSION["error_messages"] .= "

Помилка запиту на додавання користувача до БД

// Повертаємо користувача на сторінку реєстрації header("HTTP/1.1 301 Moved Permanently"); header("Location: ".$address_site."/form_register.php"); //Зупиняємо скрипт exit(); )else( $_SESSION["success_messages"] = "

Реєстрація пройшла успішно!!!
Тепер Ви можете авторизуватися використовуючи Ваш логін та пароль.

// Відправляємо користувача на сторінку авторизації header("HTTP/1.1 301 Moved Permanently"); header("Location: ".$address_site."/form_auth.php"); ) /* Завершення запиту */ $result_query_insert-> close();// Закриваємо підключення до БД $mysqli->close();

Якщо у запиті на додавання користувача до БД виникла помилка, ми додаємо повідомлення про цю помилку в сесію та повертаємо користувача на сторінку реєстрації.

Інакше, якщо все пройшло добре, в сесію ми також додаємо повідомлення, але вже приємніша, а саме кажемо користувачеві, що реєстрація пройшла успішно. І перенаправляємо його вже на сторінку із формою авторизації.

Скрипт для перевірки формату поштової адреси та довжини пароля знаходиться у файлі header.phpТому він буде діяти і на поля з цієї форми.

Запуск сесії також відбувається у файлі header.phpтому у файлі form_auth.phpсесію запускати не потрібно, бо отримаємо помилку.


Як я вже сказав, скрипт перевірки формату поштової адреси та довжини пароля тут також діє. Тому якщо користувач введе неправильну поштову адресу або короткий пароль, він відразу ж отримає повідомлення про помилку. А кнопка Увійтистане не активною.

Після усунення помилок кнопка Увійтистає активною, і користувач зможе відправити форму на сервер, де вона оброблятиметься.

Авторизація користувача

У значення атрибуту actionу фори авторизації зазначений файл auth.phpЦе означає, що форма буде оброблятися саме в цьому файлі.

І так, відкриваємо файл auth.phpта пишемо код для обробки форми авторизації. Перше, що потрібно зробити це запустити сесію і підключити файл dbconnect.phpдля з'єднання з БД.

При натисканні на посилання виходу з сайту ми потрапляємо у файл logout.php, де просто знищуємо осередки з поштовою адресою та паролем із сесії. Після цього повертаємо користувача назад на ту сторінку, на якій було натиснуто посилання вихід.

Код файлу logout.php:

На цьому все. Тепер Ви знаєте як реалізувати та обробляти форми реєстрації та авторизації користувача на своєму сайті. Ці форми зустрічаються майже кожному сайті, тому кожен програміст повинен знати, як їх створювати.

Ще ми навчилися перевіряти дані, що вводяться, як на стороні клієнта (в браузері, за допомогою JavaScript, jQuery) так і на стороні сервера (за допомогою мови PHP). Також ми навчилися реалізувати процедуру виходу із сайту.

Усі скрипти перевірені та робітники. Архів з файлами цього маленького сайту Ви можете завантажити за цим посиланням.

У майбутньому я напишу статтю де опишу. І ще планую написати статтю, де поясню, (без перезавантаження сторінки). Так що для того, щоб бути в курсі про вихід нових статей, можете підписатися на мій сайт.

При виникненні питань звертайтеся також, якщо ви помітили, якусь помилку в статті прошу вас, повідомте мені про це.

План уроку (Частина 5):

  • Створюємо HTML структуру для форми авторизації
  • Обробляємо отримані дані
  • Виводимо вітання користувача до шапки сайту
  • Сподобалася стаття?

    Не знаю чому… ні, чому не можна включати директиву register_globals я знаю, а не знаю чому в літературі, як правило, про це нічого не говориться.

    У цій статті я постараюся витягнути з танка всіх тих, хто в ньому сидить, і пояснити, що до чого (спеціально для тих, хто на бронепоїзді – прим.ред.). Все ж таки не дарма деякі хостери відключають цю директиву. Отже…

    Про те, як це працює

    У налаштуваннях PHP (файл php.ini) є така директива register_globals. Сенс її полягає в тому, що якщо вона увімкнена (register_globals = on), то всі змінні, передані через GET і POST, будуть зареєстровані автоматично як глобальні. Що це означає?

    Наприклад, ми передаємо сценарію index.php шляхом GET деяке значення page: index.php?page=2. Передане значення зберігається у масиві GET і може бути використане у сценарії як $_GET["page"]. Однак, якщо у нас включена register_globals, то для переданого значення буде створена змінна $page, яка доступна в будь-якій частині сценарію index.php.

    Невеликий підсумок та доповнення. При включеному register_globals створюється три копії змінної: у масиві GET, у масиві GLOBALS і просто сама змінна ($_GET["page"], $GLOBALS["page"], $page), у той час як при вимкненому register_globals передане значення може бути доступним лише через масив GET ($_GET["page"]). Запам'ятали.

    Небезпека використання

    Розглянемо простий приклад, щоб зрозуміти, що нам світить (від 3 до 5 років – прим.ред.). Щоб було простіше, скажу відразу, що $login та $password – це змінні, передані методом GET/POST.

    Коротко про те, що робить сценарій:

      Рядок 2. Робимо запит до БД з метою витягти цей пароль для введеного користувачем логіну.

      Рядок 3. Отримуємо цей пароль та присвоюємо його змінною $real_pass.

      Рядок 4. Порівнюємо цей і введений пароль і якщо вони збігатимуться, то змінній $check буде присвоєно true.

      Рядки 5-8. Якщо $check дорівнює true, пишемо, що авторизація проведена успішно і т.д.

    Запропонований сценарій за визначенням найдірявіший на світі і зараз я покажу Вам ці дірки. Умова – register_globals включений.

    Допустимо, передача йде методом GET. Тоді url буде виглядати приблизно так:
    www.site.com/index.php?login =admin&password =qwerty
    Зрозуміло, що відразу ж створюються глобальні змінні $login і $password. А тепер подивіться сценарій. У ньому є змінна $check. А якщо її передати через урл?

    www.site.com/index.php?login =admin&password =qwerty&check =1
    Тоді пройде перевірка співвідношення паролів і користувач виходить відразу авторизованим (адже Ви пам'ятаєте, що 1 – це true, а 0 – це false?). Той самий результат буде, якщо написати www.site.com/index.php?check =1 . І навіть якщо ви використовуєте метод POST, все одно всі подібні махінації прокотять, тому що при включеному register_globals не має значення, який у Вас метод - GET або POST.

    Думаю, у когось постало питання, а звідки крякер дізнається про змінну check, що вона за все відповідає? Якщо Ви нікому не показували сценарій, він навряд чи це дізнається. Однак не всі використовують свої сценарії, CMS та інше, а користуються тим, що є у мережі. У таких випадках крякер, наприклад, може вивчити код CMS і атакувати сайти, створені з допомогою.

    Тим не менш, не всі хостери відключають register_globals і навіть якщо Ваші сценарії будуть заточені на відсутність включеного register_globals, то крякер все одно може зламати Ваш сценарій, використовуючи вразливість цієї директиви.

    Візьмемо наш приклад. Щоб його захистити на випадок, якщо register_globals увімкнено, потрібно після рядка if ($password==$real_pass) $check =true;дописати таке: else $check =false;. У цьому випадку, навіть якщо методом GET буде передана змінна check, що дорівнює одиниці, то сценарій при неправильному паролі все одно встановить $check=false.

    Так, ще зверну увагу на те, що якщо вимкнути register_globals, то наш приклад працювати не буде. А щоб він запрацював, треба перед сценарієм написати $login=$_POST["login"]; $password = $_POST["password"];

    Підведемо підсумки…

    і зробимо два основні висновки:

    1) При включеному register_globals можна передавати різні змінні, значення яких отримувати через GET чи POST не розраховувалося.

    2) Не так небезпечний сам register_globals, як криво написаний сценарій.

    На сьогодні все! Буду дуже радий Вашим коментарям, зауваженням, пропозиціям та просто відгукам. Тому пишіть, не соромтеся!

    З побажаннями вдалого тижня,
    Олександр Шуйський