Система регистрации и авторизации необходима для любого сайта, который хранит информацию о своих пользователях. Такие системы используются на сайтах самой разнообразной тематики – от образовательных платформ, которые хранят сведения о прохождении обучающих курсов и оценках, до онлайн-магазинов, которые сохраняют историю покупок и адреса пользователей. В этом руководстве мы научим вас создавать формы регистрации и авторизации с нуля.
- Разработка форм регистрации и авторизации
- Код регистрационной формы
- Исходный код страницы авторизации
- CSS-стили для оформления форм
- Создание таблицы с учетными данными и подключение к базе данных
- Исходный код для регистрации пользователей
- Функция авторизации
- Ограничение доступа к страницам
- Типичные ошибки и способы их решения
- Некорректное имя переменной
- «Заголовки уже отправлены»
- Переменные сессии не сохраняются при переходах между страницами
Мы рассмотрим процесс создания простых форм для регистрации и авторизации пользователей. Регистрационная форма будет содержать поля для ввода имени, пароля и адреса электронной почты. Имя пользователя и адрес электронной почты при этом должны быть уникальными для каждого конкретного пользователя. В случае попытки регистрации второй учетной записи с таким же именем пользователя (или электронной почтой) будет выводиться сообщение об ошибке с пояснением о том, что такие данные уже используются в системе.
Ниже приведен HTML-код необходимый для создания формы регистрации. Сохраните его вфайле register.php.
<form method="post" action="" name="signup-form"> <div class="form-element"> <label>Username</label> <input type="text" name="username" pattern="[a-zA-Z0-9]+" required /> </div> <div class="form-element"> <label>Email</label> <input type="email" name="email" required /> </div> <div class="form-element"> <label>Password</label> <input type="password" name="password" required /> </div> <button type="submit" name="register" value="register">Register</button> </form>
Несмотря на простоту данной формы, для проведения простейшей валидации данных в ней используется HTML5. К примеру, использование type=»email» обеспечит уведомление пользователя о том, что он неправильно ввел адрес электронной почты. Кроме того, применение pattern позволит провести проверку имени пользователя – логин может состоять только из латинских букв и цифр.
Наиболее продвинутый способ валидации данных подразумевает использование jQuery – в этом случае разработчик получает полный контроль над показом, расположением и внешним видом сообщений об ошибках ввода. Подробнее о валидации на стороне клиента с использованием jQuery рассказывается в этой статье.
HTML-код страницы входа в систему приведен ниже. Сохраните его в файле login.php.
<form method="post" action="" name="signin-form"> <div class="form-element"> <label>Username</label> <input type="text" name="username" pattern="[a-zA-Z0-9]+" required /> </div> <div class="form-element"> <label>Password</label> <input type="password" name="password" required /> </div> <button type="submit" name="login" value="login">Log In</button> </form>
Для улучшения внешнего вида форм примените к ним следующие CSS-стили:
* { padding: 0; margin: 0; box-sizing: border-box; } body { margin: 50px auto; text-align: center; width: 800px; } h1 { font-family: 'Passion One'; font-size: 2rem; text-transform: uppercase; } label { width: 150px; display: inline-block; text-align: left; font-size: 1.5rem; font-family: 'Lato'; } input { border: 2px solid #ccc; font-size: 1.5rem; font-weight: 100; font-family: 'Lato'; padding: 10px; } form { margin: 25px auto; padding: 20px; border: 5px solid #ccc; width: 500px; background: #eee; } div.form-element { margin: 20px 0; } button { padding: 10px; font-size: 1.5rem; font-family: 'Lato'; font-weight: 100; background: yellowgreen; color: white; border: none; } p.success, p.error { color: white; font-family: lato; background: yellowgreen; display: inline-block; padding: 2px 10px; } p.error { background: orangered; }
В коде, приведенном выше, предусмотрено оформление заголовков и сообщений об ошибках валидации. Фрагменты HTML и CSS кода, рассмотренные выше, могут использоваться в качестве основы, поскольку ваш собственный проект может нуждаться в другом стиле оформления, а также в дополнительных полях ввода.
Следующий шаг – создание таблицы базы данных, содержащей учетные данные пользователей. В нашем случае таблица состоит всего из четырех столбцов:
- Порядковый номер ID, который для каждого нового пользователя увеличивается автоматически.
- Уникальное имя пользователя.
- Адрес электронной почты.
- Пароль.
Для быстрого создания таблицы базы данных можно использовать следующий SQL-запрос:
CREATE TABLE `users` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `username` varchar(25) NOT NULL, `password` varchar(255) NOT NULL, `email` varchar(100) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1;
Теперь создайте файл config.php и сохраните в нем приведенный далее код для подключения к базе данных:
<?php define('USER', 'root'); define('PASSWORD', ''); define('HOST', 'localhost'); define('DATABASE', 'test'); try { $connection = new PDO("mysql:host=".HOST.";dbname=".DATABASE, USER, PASSWORD); } catch (PDOException $e) { exit("Error: " . $e->getMessage()); } ?>
В приведенном выше коде замените название базы данных на то, которое вы используете для своего собственного сайта.
Теперь пришла очередь написать код для регистрации пользователей. Главная функция этого кода – проверить, не зарегистрирован ли уже аналогичный адрес электронной почты в базе данных. Если нет, новое имя пользователя вместе с адресом его электронной почты и паролем передаются для сохранения в базе данных.
Сохраните приведенный далее код в начале файла registration.php:
<?php session_start(); include('config.php'); if (isset($_POST['register'])) { $username = $_POST['username']; $email = $_POST['email']; $password = $_POST['password']; $password_hash = password_hash($password, PASSWORD_BCRYPT); $query = $connection->prepare("SELECT * FROM users WHERE email=:email"); $query->bindParam("email", $email, PDO::PARAM_STR); $query->execute(); if ($query->rowCount() > 0) { echo '<p class="error">Этот адрес уже зарегистрирован!</p>'; } if ($query->rowCount() == 0) { $query = $connection->prepare("INSERT INTO users(username,password,email) VALUES (:username,:password_hash,:email)"); $query->bindParam("username", $username, PDO::PARAM_STR); $query->bindParam("password_hash", $password_hash, PDO::PARAM_STR); $query->bindParam("email", $email, PDO::PARAM_STR); $result = $query->execute(); if ($result) { echo '<p class="success">Регистрация прошла успешно!</p>'; } else { echo '<p class="error">Неверные данные!</p>'; } } } ?>
На первом этапе выполнения кода включается config.php, начинается сессия. Так мы получаем возможность сохранить любую информацию для дальнейшего использования на всех страницах сайта.
Далее, с помощью $_POST[‘register’] мы проверяем, нажал ли пользователь кнопку «Регистрация». Следует помнить, что пароли нельзя сохранять в виде незашифрованного текста. Поэтому наш код использует функцию password_hash() и сохраняет пароль в хэшированном виде. Эта функция записывает пароль в базу данных в виде хэш-строки, состоящей из 60 случайных символов.
После этого мы проверяем, существует ли предоставленный пользователем адрес электронной почты в базе данных. Если это так, пользователь получит соответствующее сообщение. Если же такого email-адреса в базе данных, используемой сайтом, нет, вся введенная информация сохраняется в базе данных и пользователь видит сообщение об успешной регистрации.
На предыдущем этапе мы уже сохранили код для формы авторизации пользователей в системе. На этом этапе мы будем проверять, соответствуют ли введенные пользователем данные учетной записи, сохраненной в базе.
Приведенный далее код должен располагаться в начале файла login.php:
<?php session_start(); include('config.php'); if (isset($_POST['login'])) { $username = $_POST['username']; $password = $_POST['password']; $query = $connection->prepare("SELECT * FROM users WHERE username=:username"); $query->bindParam("username", $username, PDO::PARAM_STR); $query->execute(); $result = $query->fetch(PDO::FETCH_ASSOC); if (!$result) { echo '<p class="error">Неверные пароль или имя пользователя!</p>'; } else { if (password_verify($password, $result['password'])) { $_SESSION['user_id'] = $result['id']; echo '<p class="success">Поздравляем, вы прошли авторизацию!</p>'; } else { echo '<p class="error"> Неверные пароль или имя пользователя!</p>'; } } } ?>
Важно отметить, что мы не проверяем правильность имени и пароля одновременно. Поскольку пароль сохранен в хэшированном виде, сначала необходимо запросить хэш с помощью предоставленного имени пользователя. Когда мы получим хэш, можно будет проверить предоставленный пользователем пароль на соответствие хэшированному – с помощью функции password_verify().
Как только мы получаем подтверждение правильности пароля, мы назначаем переменную $_SESSION[‘user_id’] для ID пользователя из базы данных. При необходимости на этом этапе передаются и значения для других переменных.
На большинстве сайтов, запрашивающих учетные данные посетителей, есть страницы, на которых зарегистрированные пользователи хранят свою личную информацию. Для защиты подобных страниц от несанкционированного доступа можно использовать переменные сессии. Если переменная сессии не создана, пользователь перенаправляется на страницу авторизации. Если переменная сессии создана, пользователь видит содержимое страницы:
<?php session_start(); if(!isset($_SESSION['user_id'])){ header('Location: login.php'); exit; } else { // Покажите пользователю страницу } ?>
Все, что нужно сделать для ограничения или предоставления доступа – это использовать в начале приведенного выше скрипта строку session_start().
При использовании скрипта для ограничения доступа неавторизованных пользователей обычно возникают три типа ошибок.
Чаще всего ошибки в работе скрипта связаны с неверными именами переменных – как правило, с использованием букв в неправильном регистре. Именно поэтому крайне важно придерживаться одного и того же шаблона при выборе имен. К примеру, ключи в функции $_POST основаны на значениях, полученных из полей ввода в формах. Это означает, что $_POST[‘USERNAME’] и $_POST[‘username’] получат разные значения.
Некоторые функции, например session_start() и header(), изменяют HTTP-заголовки. Поскольку PHP сбрасывает все заголовки перед выводом любых данных, важно вызывать все подобные функции до того, как вы начнете что-либо выводить – включая фрагменты сырого HTML или случайные пробелы перед открывающим тегом <?php.
Вы можете использовать переменные сессии только в том случае, если на странице осуществлен вызов функции session_start(). Если значения суперглобальной переменной $_SESSION вам не доступны, причина этого заключается в том, что вы забыли вызвать session_start(). Помните о том, что функцию надо вызывать перед выводом чего-либо на страницу сайта. В противном случае вы получите ошибку «Заголовки уже отправлены», рассмотренную выше.
Внимание! Данная статья является устаревшей и носит исключительно ознакомительный характер. Если вас интересует авторизация на PHP, рекомендуем прочитать следующий материал по использованию готовых библиотек авторизации.
В этой статье вы узнаете, как сделать PHP-авторизацию (authentication) на сайте с помощью данных, полученных от пользователя при регистрации. Будем использовать таблицу MySQL, а сама PHP-авторизация будет работать с применением сессий и cookie. Материал не следует рассматривать, как пошаговое руководство. Зато он помогает понять, как работает PHP-авторизация в целом.
В первую очередь нужно сверстать главную страницу веб-сайта, поместив её в корне в папку template. Для этого создаём файл index.html с формой ввода логина и пароля, кнопкой «Вход», вот её код:
<form action="/" method="post"> Логин: <input type="text" name="login" /> Пароль: <input type="password" name="password" /> <input type="submit" value="Войти" name="log_in" /> </form>Мы используем метод передачи post, который необходим. Нам ведь не нужно, чтобы в процессе PHP-авторизации пароль и логин «светились» в адресной строке.
Когда форма готова, создаём главный контроллер — наиболее важный файл сайта, лежащий в корне — index.php. Как раз он и будет запускаться во время входа. Код выглядит следующим образом:
<? include ('lib/connect.php'); //подключаемся к БД include ('lib/module_global.php'); //подключается файл с глобальными функциями if($_GET['action'] == "out") out(); //если передана переменная action, «разавторизируем» пользователя if (login()) //вызываем функцию login, которая определяет, авторизирован пользователь или нет { $UID = $_SESSION['id']; //если пользователь авторизирован, присваиваем переменной $UID его id $admin = is_admin($UID); //определяем, админ ли пользователь } else //если пользователь не авторизирован, проверяем, была ли нажата кнопка входа на сайт { if(isset($_POST['log_in'])) { $error = enter(); //функция входа на сайт if (count($error) == 0) //если ошибки отсутствуют, авторизируем пользователя { $UID = $_SESSION['id']; $admin = is_admin($UID); } } } include ('tpl/index.html'); //подключается файл с формой ?>Теперь разберёмся подробнее, как всё работает.
В первых 3 строках просто подключаются файлы с функциями, необходимыми для дальнейшего использования в коде. О них поговорим потом. Далее проверяем, был ли передан get-параметр action=out. В случае его передачи пользователь нажал на ссылку выхода с веб-сайта. Код ссылки, который нужно добавить в файл, содержащий код формы для входа:
<a href="/?action=out">Выход</a>Потом у нас идёт условие, которое проверяет, авторизован ли ты (if (login())). То есть функция возвращает нам true, если юзер вошёл на сайт. В противном случае возвращается false. Когда вернулось true, в переменную $UID записывается id юзера. Что касается переменной $admin, то в неё пишется результат работы функции is_admin($UID). Она определяет, является ли наш юзер админом, возвращая true, если это так и false в обратном случае. Потом эти 2 переменные понадобятся, чтобы вывести определённые элементы на странице.
Итак, форму PHP-авторизации можно вывести следующим условием:
<? If($UID) //если переменной нет, выводим форму {?> <form action="/" method="post"> Логин: <input type="text" name="login" /> Пароль: <input type="password" name="password" /> <input type="submit" value="Войти" name="log_in" /> </form> <?} ?>Аналогичная ситуация и с переменной $admin. Последний код тоже можно поместить в файл с формой.
Если функция login() вернёт false (юзер не вошёл на сайт), мы проверим, а нажал ли он вообще на кнопку входа на сайт, которая включена в нашу форму PHP-авторизации:
if(isset($_POST['log_in']))Если это так, запускается функция enter(), авторизующая пользователя. Если ошибки отсутствуют, а пользователь вошёл успешно, создаём те же две переменные: $UID и $admin. В обратном случае переменные не создаются никакие, ведь пользователь является гостем.
Давайте посмотрим на алгоритм работы:
А теперь рассмотрим все функции, вызываемые в коде. Вот функция входа на сайт:
function enter () { $error = array(); //массив для ошибок if ($_POST['login'] != "" && $_POST['password'] != "") //если поля заполнены { $login = $_POST['login']; $password = $_POST['password']; $rez = mysql_query("SELECT * FROM users WHERE login=$login"); //запрашивается строка из базы данных с логином, введённым пользователем if (mysql_num_rows($rez) == 1) //если нашлась одна строка, значит такой юзер существует в базе данных { $row = mysql_fetch_assoc($rez); if (md5(md5($password).$row['salt']) == $row['password']) //сравнивается хэшированный пароль из базы данных с хэшированными паролем, введённым пользователем { //пишутся логин и хэшированный пароль в cookie, также создаётся переменная сессии setcookie ("login", $row['login'], time() + 50000); setcookie ("password", md5($row['login'].$row['password']), time() + 50000); $_SESSION['id'] = $row['id']; //записываем в сессию id пользователя $id = $_SESSION['id']; lastAct($id); return $error; } else //если пароли не совпали { $error[] = "Неверный пароль"; return $error; } } else //если такого пользователя не найдено в базе данных { $error[] = "Неверный логин и пароль"; return $error; } } else { $error[] = "Поля не должны быть пустыми!"; return $error; } }Сначала функция проверит, а заполнено ли поле для ввода пароля и логина для PHP-аутентификации. Если да, работа программы продолжается, в противном случае в массив $error пишется текст ошибки, и происходит возвращение в основную программу, которая после того, как узнает размерность полученного массива, пользователя не авторизует.
Но если работа функции enter() будет продолжена, мы проверим, а существует ли в базе данных запись с таким ником. Когда записи нет, возвращается массив с ошибкой. Когда есть, введённый пароль сравнивается со значением, которое хранится в БД.
Пароли сравниваются не в чистом виде, т. к. в базе данных они хэшированы функцией md5(). Значит это следующее: прежде чем приступить к сравнению, нужно хэшировать тем же алгоритмом пароль, введённый пользователем при попытке пройти аутентификацию/авторизацию.
Когда хэши совпадают, происходит авторизация с помощью скрипта. При отсутствии совпадений, возвращается ошибка.
Давайте подробно остановимся на том, что значит «авторизироваться». В нашем скрипте информация о PHP-авторизации хранится в cookie и сессии. В сессию записывается id пользователя:
Кроме того, создаются 2 cookie: login и password. Продолжительность жизни — 50 тыс. секунд. В первый пишется логин, во 2-й — хэш пароля.
В данной строке выполняется функция, которая устанавливает время последней активности юзера. Код:
function lastAct($id) { $tm = time(); mysql_query("UPDATE users SET online='$tm', last_act='$tm' WHERE id='$id'"); }С помощью функции перезаписываются поля online и last_act в базе данных. Здесь, кстати, важно убедиться, что эти поля существуют (оба имеют тип int).
Теперь посмотрим на алгоритм работы функции enter():
Идём дальше. Следующая функция нужна для проверки, авторизирован ли юзер на сайте — login().
function login () { ini_set ("session.use_trans_sid", true); session_start(); if (isset($_SESSION['id']))//если сесcия есть { if(isset($_COOKIE['login']) && isset($_COOKIE['password'])) //если cookie есть, обновляется время их жизни и возвращается true { SetCookie("login", "", time() - 1, '/'); SetCookie("password","", time() - 1, '/'); setcookie ("login", $_COOKIE['login'], time() + 50000, '/'); setcookie ("password", $_COOKIE['password'], time() + 50000, '/'); $id = $_SESSION['id']; lastAct($id); return true; } else //иначе добавляются cookie с логином и паролем, чтобы после перезапуска браузера сессия не слетала { $rez = mysql_query("SELECT * FROM users WHERE id='{$_SESSION['id']}'"); //запрашивается строка с искомым id if (mysql_num_rows($rez) == 1) //если получена одна строка { $row = mysql_fetch_assoc($rez); //она записывается в ассоциативный массив setcookie ("login", $row['login'], time()+50000, '/'); setcookie ("password", md5($row['login'].$row['password']), time() + 50000, '/'); $id = $_SESSION['id']; lastAct($id); return true; } else return false; } } else //если сессии нет, проверяется существование cookie. Если они существуют, проверяется их валидность по базе данных { if(isset($_COOKIE['login']) && isset($_COOKIE['password'])) //если куки существуют { $rez = mysql_query("SELECT * FROM users WHERE login='{$_COOKIE['login']}'"); //запрашивается строка с искомым логином и паролем @$row = mysql_fetch_assoc($rez); if(@mysql_num_rows($rez) == 1 && md5($row['login'].$row['password']) == $_COOKIE['password']) //если логин и пароль нашлись в базе данных { $_SESSION['id'] = $row['id']; //записываем в сесиию id $id = $_SESSION['id']; lastAct($id); return true; } else //если данные из cookie не подошли, эти куки удаляются { SetCookie("login", "", time() - 360000, '/'); SetCookie("password", "", time() - 360000, '/'); return false; } } else //если куки не существуют { return false; } } }Возникает вопрос, почему для авторизации используем и сессию, и cookie? Всё дело в том, что при закрытии браузера сессия «умирает», а пользователь автоматически разлогинивается. А вот cookie хранятся определённое время, задаваемое нами (50 тыс. секунд).
Дальше у нас функция online(). Её нужно запускать первой на всех модулях и страницах будущего сайта. В первую очередь, она проверяет, прошёл ли пользователь PHP-авторизацию/аутентификацию, что важно для дальнейшей работы скрипта. Во вторую очередь, она выполняет обновление времени последней активности, а также помогает в перспективе выводить систему онлайн-пользователей.
Наша функция вернёт true, когда юзер авторизирован, а в обратном случае — false. При этом в процессе работы обновится время жизни cookie или они будут созданы, если вообще не существуют.
Очередной алгоритм работы:
Когда есть сессия и cookie, обновляется время жизни cookie. Чтобы это реализовать, они удаляются, время смерти устанавливается на одну секунду раньше текущего времени, потом устанавливаете заново. Также нужно учесть, что функция lastAct() обновляет время последней активности. Возвращается, разумеется, true.
Когда сессия есть, а cookie почему то нет, то по id юзера мы получаем из базы данных логин и хэш пароля, потом пишем их в cookie. Возвращается true.
Когда сессии нет, проверяем, существуют ли cookie. Традиционный пример — PHP-авторизация после перезапуска браузера, когда сессия слетела, но cookie всё ещё живы. Становится сложнее, ведь нужно проверить, а совпадает ли пара пароль-логин с какой-нибудь строкой из базы данных. Ведь пользователь легко мог сменить cookie в настройках для сайта. Если пара нашлась, создаётся переменная сессии, возвращается true. Если пара не нашлась, возвращается false.
Если у нас самый печальный вариант — ни сессии, ни cookie не оказалось, возвращается false.
Сейчас глянем на функцию is_admin($UID), определяющую является ли user админом. Если вам это не надо, опустите данную функцию и её вызовы в контроллере. Но учтите, что для вывода контента на страницу для админов она бывает полезна. К тому же, она проста и основана на одном столбце в базе данных в таблице users (столбец prava, тип int).
Когда наш юзер обыкновенный пользователь, значению в столбце присваивается 0, иначе — 1. Соответственно, в первом случае вернётся false, во втором — true.
function is_admin($id) { @$rez = mysql_query("SELECT prava FROM users WHERE id='$id'"); if (mysql_num_rows($rez) == 1) { $prava = mysql_result($rez, 0); if ($prava == 1) return true; else return false; } else return false; }Последняя функция — это out(). Она проста и удаляет все «следы» юзера — и сессию, и cookie.
function out () { session_start(); $id = $_SESSION['id']; mysql_query("UPDATE users SET online=0 WHERE id='$id'"); //обнуляется поле online, говорящее, что пользователь вышел с сайта (пригодится в будущем) unset($_SESSION['id']); //удалятся переменная сессии SetCookie("login", ""); //удаляются cookie с логином SetCookie("password", ""); //удаляются cookie с паролем header('Location: http://'.$_SERVER['HTTP_HOST'].'/'); //перенаправление на главную страницу сайта }Код всех наших функций нужно поместить в файл lib/module_global.php, подключаемый в начале работы контроллера.
Итак, мы написали функциональную, но простую PHP-регистрацию/аутентификацию/авторизацию для сайта. Также заложили фундамент для дальнейших возможностей по администрированию и не только. Такая PHP-авторизация не слетит после перезапуска браузера, т. к. мы используем cookie. Предусмотрен и выход с сайта.
Источник: https://true-coder.ru/php/pishem-avtorizaciyu-na-php.html.
От автора: рано или поздно каждый веб-разработчик сталкивается с задачей по ограничению доступа к некоей странице/страницам или каталогу. Это может быть просто секретная страница на сайте, административная часть сайта или любой другой раздел, доступ к которому мы хотим ограничить и предоставлять только по паролю. Для этого можно, конечно же, воспользоваться средствами сервера. Думаю, на любом современном хостинге есть функция паролирования директории, где можно создать пользователя, назначить ему пароль и, после паролирования директории, доступ к закрытому каталогу будет предоставлен только после правильного ввода логина и пароля. Но иногда хочется написать что-то самому, что-то быстрое, простое, но вместе с тем — надежное…
В этом уроке мы попробуем написать свою простую систему авторизации. У нас будет секретная страница — допустим, это будет страница администратора, доступ к которой мы будем предоставлять только для авторизованного пользователя. Наша система авторизации будет основана на работе механизма сессий. Перед продолжением этого урока я рекомендую Вам ознакомиться с одним из предыдущих своих уроков, в котором мы, в частности, рассматриваем работу сессий — //webformyself.com/kak-opredelit-ip-adres-polzovatelya/.
Время ролика: 31:32
Ссылка для скачивания исходников: Скачать исходники
Ссылка для скачивания всего архива (видео+исходники): Скачать одним архивом. Размер: 47.7 mb.
Бесплатный курс по PHP программированию
Освойте курс и узнайте, как создать веб-приложение на PHP с полного нуля
Получить курс сейчас!
Вкратце всю работу с сессиями можно разделить на 3 этапа:
Открытие сессии. На всех страницах, где подразумевается работа с сессиями, обязательно должен быть осуществлен старт сессии функцией session_start().
Регистрация сессионных переменных.
Разрегистрирование сессионных переменных при помощи функции unset() и закрытие сессии функцией session_destroy().
Шаг 1
Итак, для нашей работы создадим 3 файла — Главная страница (index.php), Контакты (contact.php) и Админка (admin.php). Обращаю внимание на то, что расширение файла, к которому мы будем ограничивать доступ должно быть .php. Как Вы догадались, ограничивать доступ мы будем к файлу admin.php. Код всех файлов самый простой — это своеобразное меню в строку со ссылками на другие страницы, и под ним индивидуальный текст каждой страницы, чтобы мы могли отличать их друг от друга. Вот, к примеру, код индексной страницы:
<p><a href=«index.php»>Главная</a> | <a href=«contact.php»>Контакты</a> | <a href=«admin.php»>Админка</a></p> <hr /> Это главная страница |
Остальные страницы, как я сказал, отличаются от нее только текстом после тега линии. Я не стал делать полноценные страницы с мета-тегами, поскольку наша задача состоит только в ограничении доступа к некоей странице.
Шаг 2
Пока что мы свободно можем ходить по всем страницам, включая страницу админки. Как же мы ограничим к ней доступ? Каков вообще будет алгоритм? Мы будем делать следующее: в самом начале страницы мы будем проверять, есть ли нужная нам метка в сессии или, проще говоря, существует ли определенная сессионная переменная (также можно проверять равно ли значение сессионной переменной определенному значению). Если такой переменной нет, значит пользователь, запрашивающий эту страницу, не авторизован, а значит мы осуществим его редирект на страницу авторизации, где ему будет предложено заполнить форму с именем и паролем. Алгоритм предельно прост — реализуем его. Переходим к файлу admin.php, открываем в самом верху конструкцию PHP и напишем такой код:
<?php session_start(); if(!$_SESSION[‘admin’]){ header(«Location: enter.php»); exit; } ?> |
Давайте теперь прочитаем это код. Во-первых, мы открыли сессию, как Вы помните — это обязательное условие при работе с сессиями. Далее, мы создали простое условие, которое можно прочитать так: «если в массиве $_SESSION не существует элемента admin — будем выполнять блок действий, заключенный в операторные скобки». А в блоке кода мы при помощи функции header() производим редирект пользователя на страницу enter.php (это страница авторизации). После функции header() обязательно завершаем выполнение скрипта при помощи функции exit(). Если же условие не выполнится, т.е., в массиве $_SESSION будет элемент admin — это значит, что пользователь уже успешно авторизован, и мы пропустим блок действия в операторных скобках, т.е., никакого редиректа происходить не будет, и мы покажем запрошенную страницу.
Шаг 3
Теперь нам нужно создать страницу авторизации — enter.php. Для этого скопируем код, к примеру, страницы contact.php, создадим новый файл и вставим в него скопированный код. Файл сохраняем под именем enter.php. Теперь на этой странице напишем простенькую форму для ввода логина и пароля:
<p><a href=«index.php»>Главная</a> | <a href=«contact.php»>Контакты</a> | <a href=«admin.php»>Админка</a></p> <hr /> Это страница авторизации. <br /> <form method=«post»> Username: <input type=«text» name=«user» /><br /> Password: <input type=«password» name=«pass» /><br /> <input type=«submit» name=«submit» value=«Войти» /> </form> |
Здесь все просто. В форме 2 поля: поле для ввода логина (ему мы дали имя «user») и поле для пароля (с именем «pass»). Также мы создали кнопку (имя «submit»), по нажатию на которую будут отосланы данные из формы. Данные отсылаются методом post — это мы указали в атрибуте method тега form — и будут обработаны на этой же странице. Теперь мы можем попробовать зайти на страницу админки. Если все сделано без ошибок — мы туда попасть не сможем, а неизменно будем оказываться на странице авторизации.
Замечательно!
Шаг 4
Далее нам нужно написать на странице с формой ее обработчик, который будет принимать данные из формы и сравнивать, совпадают ли логин и пароль из формы с теми, которые есть у нас. Для этого откроем вверху страницы авторизации конструкцию PHP и начнем писать код. Для начала мы должны открыть сессию — ведь именно здесь мы будем создавать метку в сессии, если получены верные логин и пароль. На этой же странице мы будем хранить логин и пароль администратора. Обычно эти данные хранятся в базе данных (БД), но у нас будет только 1 пользователь (администратор), а потому хранить его данные для входа в БД не совсем рационально. Если же пользователей будет не один, т.е., мы, к примеру, пишем проект, в котором имеется регистрация, то, конечно же, без БД в таком случае обойтись будет сложно.
Итак, наш логин будет «admin» и хранить мы его будем в переменной $admin. Пароль будет «mypass» и он будет храниться в переменной $pass. Но хранить пароли в открытом виде не принято — это противоречит принципам безопасности. Хранить пароль мы будем в зашифрованном виде, а зашифровать его нам поможет функция md5(). Эта функция шифрует строку по специальному алгоритму, и на выходе мы получаем строку из 32 символов (ее называют хеш). Если мы зашифруем строку «mypass» (это можно сделать, например, в файле contact.php):
<?php echo md5(‘mypass’); ?> |
то на выходе получим строку «a029d0df84eb5549c641e04a9ef389e5» — это и будет наш зашифрованный пароль. Пока что код страницы авторизации будет таким:
<?php session_start(); $admin = ‘admin’; $pass = ‘a029d0df84eb5549c641e04a9ef389e5’; ?> <p><a href=«index.php»>Главная</a> | <a href=«contact.php»>Контакты</a> | <a href=«admin.php»>Админка</a></p> <hr /> Это страница авторизации. <br /> <form method=«post»> Username: <input type=«text» name=«user» /><br /> Password: <input type=«password» name=«pass» /><br /> <input type=«submit» name=«submit» value=«Войти» /> </form> |
Бесплатный курс по PHP программированию
Освойте курс и узнайте, как создать веб-приложение на PHP с полного нуля
Получить курс сейчас!
Шаг 5
Теперь проверим то, что мы получили из формы с тем, что у нас есть в переменных с логином и паролем. Делать это мы будем по условию — только в том случае, если нажата кнопка формы. Как мы можем это проверить? У кнопки есть имя («submit»), а данные мы передаем методом post. Соответственно, мы можем просто проверить, существует ли элемент submit в массиве $_POST. Если есть — кнопка была нажата, и мы будем выполнять действия по проверке присланных данных, иначе — ничего делать не будем. После объявления логина и пароля пишем условие:
if($_POST[‘submit’]){ if($admin == $_POST[‘user’] AND $pass == md5($_POST[‘pass’])){ $_SESSION[‘admin’] = $admin; header(«Location: admin.php»); exit; }else echo ‘<p>Логин или пароль неверны!</p>’; } |
Условие по проверке логина и пароля мы сделали как бы двойным. Сделано это при помощи логического оператора AND (его также можно записать таким образом — «&&»). Условие можно прочитать так: «если(переменная $admin равна элементу user в массиве $_POST И переменная $pass равна хешу элемента pass в массиве $_POST) то {выполняем блок действий}else выводим на экран текст ‘Логин или пароль неверны!’
Если же пара логин-пароль совпадает, то мы регистрируем сессионную переменную $_SESSION[‘admin’] и перенаправляем пользователя на страницу админки — admin.php.
Попробуем теперь протестировать то, что мы уже создали. Если мы введем заведомо ложные логин и пароль, то получим предупреждающее сообщение, что «Логин или пароль неверны!». Попробуем теперь ввести правильные данные для входа. Если мы нигде не ошиблись, то после нажатия на кнопку «Войти» мы окажемся на странице админки.
Отлично!
Шаг 6
Теперь осталось дописать некоторые мелочи. К примеру, мы сейчас авторизованы в системе, но если мы введем в адресной строке адрес страницы авторизации, то спокойно попадем на нее и увидим форму авторизации. Такого быть не должно — форму должен видеть только неавторизованный пользователь. Как мы можем исправить это? Помним, что на странице admin.php мы проверяли, есть ли метка в сессии. Если ее нет — мы переводили пользователя на страницу авторизации. Здесь мы можем сделать то же самое, только наоборот. Т.е., мы также проверяем, есть ли метка в сессии. Только теперь мы будем переводить пользователя на страницу админки, если такая метка есть. Это, в принципе, логично. Если есть метка, значит пользователь уже авторизован, и мы его можем перевести на страницу админки. На странице enter.php после старта сессии допишем такой код:
if($_SESSION[‘admin’]){ header(«Location: admin.php»); exit; } |
Теперь если авторизованный пользователь попробует ввести в адресную строку имя страницы авторизации — он будет переведен на страницу админки. Не авторизованный пользователь же сможет свободно попасть на страницу авторизации.
Шаг 7
Следующий момент, который нам нужно предусмотреть — это реализация выхода авторизованного пользователя, т.е., допустим, администратор закончил свою работу и ему нужно выйти, чтобы никто посторонний не смог работать под его учетной записью. Для этого добавим на странице admin.php ссылку «Выход». Ссылка будет вести на эту же страницу, только к ней будет добавлен нужный нам параметр. Параметр добавляется при помощи вопросительного знака:
<a href=«admin.php?do=logout»>Выход</a> |
Эту ссылку можно поставить в том месте, в котором нам нужно — я поставлю ее после текста страницы. Относительно параметра — он будет передан методом GET (вспоминаем, что из формы мы передавали данные вторым параметром — POST). При использовании этого метода данные присоединяются к адресу в адресной строке и отделены от адреса как раз вопросительным знаком. Мы передаем один параметр — do — и при этом присвоили ему значение «logout». Как теперь мы можем разавторизовать пользователя? Очень просто — здесь нам помогут второй и третий этапы при работе с сессиями. При загрузке страницы мы можем проверить значение элемента do из массива $_GET. Если оно будет равно строке «logout» — мы просто разрегистрируем сессионную переменную $_SESSION[‘admin’] и разрушим сессию. Соответственно, метки в сессии после этого не будет и в следующем блоке, где мы проверяем наличие метки, пользователь будет перенаправлен на страницу авторизации. Все просто.
Итак, на странице admin.php допишем условие после старта сессии (до проверки наличия метки):
if($_GET[‘do’] == ‘logout’){ unset($_SESSION[‘admin’]); session_destroy(); } |
Теперь можно попробовать перейти по ссылке «Выход». После выхода мы окажемся на странице авторизации и увидим форму для авторизации. Попасть теперь на страницу админки мы не сможем, пока не авторизуемся.
Шаг 8
И последний штрих. Мы можем ограничивать доступ не только к странице админки, но и к любой другой. Для этого достаточно открыть сессию и проверить наличие метки в ней. Чтобы не копировать на каждую новую страницу эти блоки кода — мы их можем вынести в отдельный файл (auth.php) и затем просто подключать этот файл на страницах, к которым нужно ограничить доступ по паролю. Содержимое файла auth.php будет таким:
<?php session_start(); if($_GET[‘do’] == ‘logout’){ unset($_SESSION[‘admin’]); session_destroy(); } if(!$_SESSION[‘admin’]){ header(«Location: enter.php»); exit; } ?> |
Теперь вместо этой конструкции мы в файле admin.php просто подключим файл auth.php:
<?php require «auth.php»; ?> |
И на любой странице, к которой мы хотим ограничить доступ, теперь достаточно будет подключить этот файл таким способом.
Заключение
На этом наш урок завершен, мы выполнили поставленную в уроке задачу — написали свою простенькую систему авторизации. Конечно, как говорилось выше, для серьезных проектов такая система авторизации мало подходит, поскольку пользователей у нас может быть больше одного и хранить их нужно в БД. Да и шифрование пароля функцией md5() часто также бывает неэффективно, поскольку существуют сервисы с базами хешей… но для нас главное было понять принцип построения системы авторизации, а строится она именно по такому принципу. Итак, урок окончен. До новых встреч.
Автор: Кудлай Андрей
Редакция: Рог Виктор и Андрей Бернацкий. Команда webformyself.
E-mail: contact@webformyself.com
Бесплатный курс по PHP программированию
Освойте курс и узнайте, как создать веб-приложение на PHP с полного нуля
Получить курс сейчас!
Разработка веб-приложения на PHP
Скачайте видеокурс и узнайте, как создать веб-приложение на PHP
Скачать
This is a tutorial for creating a login system with the help of HTML, PHP, and MySQL. Your website needs to be dynamic and your visitors need to have instant access to it. Therefore, they want to log in as many times as possible. The login authentication system is very common for any web application. It allows registered users to access the website and members-only features. It is also helpful when we want to store information for users. It covers everything from shopping sites, educational sites, and membership sites, etc.
This tutorial is covered in 4 parts.
Table of Contents
- Signup System
- Login System
- Welcome Page
- Logout Script
1) Building a Signup system
In this part, We will create a signup system that allows users to create a new account to the system. Our first step is to create a HTML registration form. The form is pretty simple to create. It only asks for a name, email, password, and confirm password. Email addresses will be unique for every user. Multiple accounts for the same email address are not allowed. It will show an error message to the users who try to create multiple accounts with the same email address.
Step 1: Creating Registration Form in HTML
We will create a PHP file named register.php with the following code in it. This is a simple HTML form with some basic validation. If you are not familiar with HTML then you can get it from many online sites who give ready-made html5 login form templates.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Sign Up</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-12">
<h2>Register</h2>
<p>Please fill this form to create an account.</p>
<form action="" method="post">
<div class="form-group">
<label>Full Name</label>
<input type="text" name="name" class="form-control" required>
</div>
<div class="form-group">
<label>Email Address</label>
<input type="email" name="email" class="form-control" required />
</div>
<div class="form-group">
<label>Password</label>
<input type="password" name="password" class="form-control" required>
</div>
<div class="form-group">
<label>Confirm Password</label>
<input type="password" name="confirm_password" class="form-control" required>
</div>
<div class="form-group">
<input type="submit" name="submit" class="btn btn-primary" value="Submit">
</div>
<p>Already have an account? <a href="login.php">Login here</a>.</p>
</form>
</div>
</div>
</div>
</body>
</html>
The output of the above HTML form will look like this.
All the input fields are required by adding the "required"
attribute which is the default HTML attribute. The use of type="email"
will validate the email address provided by users and gives an error if the email address is not valid. For the registration form, we have used bootstrap for rapid development. If you want to save your time on HTML code you can always use some free html5 templates for your project.
Step 2: Creating the MySQL Database Table
You will need to create a new database with any suitable name you want. After that please execute the below SQL query to create the user’s table inside your newly created MySQL database.
CREATE TABLE `users` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(75) NOT NULL,
`password` varchar(255) NOT NULL,
`email` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1;
Step 3: Creating Database Configuration File
Now, we have created the users table. Let’s create a new PHP file named config.php to connect with the MySQL database. Paste the following code in the config.php file and change the database name to whatever you choose while creating the database.
<?php
define('DBSERVER', 'localhost'); // Database server
define('DBUSERNAME', 'root'); // Database username
define('DBPASSWORD', ''); // Database password
define('DBNAME', 'demo'); // Database name
/* connect to MySQL database */
$db = mysqli_connect(DBSERVER, DBUSERNAME, DBPASSWORD, DBNAME);
// Check db connection
if($db === false){
die("Error: connection error. " . mysqli_connect_error());
}
?>
Step 4: Creating a Session File
Let’s create a file named session.php. In this file, we will start the session and check if a user is already logged in, if yes then we will redirect the user to welcome.php file.
<?php
// Start the session
session_start();
// if the user is already logged in then redirect user to welcome page
if (isset($_SESSION["userid"]) && $_SESSION["userid"] === true) {
header("location: welcome.php");
exit;
}
?>
Step 5: Create Registration Form in PHP
Finally, it’s time to create a PHP code that allows users to register their accounts into the system. This PHP code will alert users with an error if any user is already registered with the same email address.
Replace the following code in the register.php file.
<?php
require_once "config.php";
require_once "session.php";
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['submit'])) {
$fullname = trim($_POST['name']);
$email = trim($_POST['email']);
$password = trim($_POST['password']);
$confirm_password = trim($_POST["confirm_password"]);
$password_hash = password_hash($password, PASSWORD_BCRYPT);
if($query = $db->prepare("SELECT * FROM users WHERE email = ?")) {
$error = '';
// Bind parameters (s = string, i = int, b = blob, etc), in our case the username is a string so we use "s"
$query->bind_param('s', $email);
$query->execute();
// Store the result so we can check if the account exists in the database.
$query->store_result();
if ($query->num_rows > 0) {
$error .= '<p class="error">The email address is already registered!</p>';
} else {
// Validate password
if (strlen($password ) < 6) {
$error .= '<p class="error">Password must have atleast 6 characters.</p>';
}
// Validate confirm password
if (empty($confirm_password)) {
$error .= '<p class="error">Please enter confirm password.</p>';
} else {
if (empty($error) && ($password != $confirm_password)) {
$error .= '<p class="error">Password did not match.</p>';
}
}
if (empty($error) ) {
$insertQuery = $db->prepare("INSERT INTO users (name, email, password) VALUES (?, ?, ?);");
$insertQuery->bind_param("sss", $fullname, $email, $password_hash);
$result = $insertQuery->execute();
if ($result) {
$error .= '<p class="success">Your registration was successful!</p>';
} else {
$error .= '<p class="error">Something went wrong!</p>';
}
}
}
}
$query->close();
$insertQuery->close();
// Close DB connection
mysqli_close($db);
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Sign Up</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-12">
<h2>Register</h2>
<p>Please fill this form to create an account.</p>
<?php echo $success; ?>
<?php echo $error; ?>
<form action="" method="post">
<div class="form-group">
<label>Full Name</label>
<input type="text" name="name" class="form-control" required>
</div>
<div class="form-group">
<label>Email Address</label>
<input type="email" name="email" class="form-control" required />
</div>
<div class="form-group">
<label>Password</label>
<input type="password" name="password" class="form-control" required>
</div>
<div class="form-group">
<label>Confirm Password</label>
<input type="password" name="confirm_password" class="form-control" required>
</div>
<div class="form-group">
<input type="submit" name="submit" class="btn btn-primary" value="Submit">
</div>
<p>Already have an account? <a href="login.php">Login here</a>.</p>
</form>
</div>
</div>
</div>
</body>
</html>
Once user click on submit button it will check if $_SERVER["REQUEST_METHOD"] == "POST"
and $_POST['submit']
variable has been set. For security concerns, we always suggest not to store the password as plain text in the database. We have used password_hash()
function which creates a new password hash using a strong one-way hashing algorithm.
The above PHP script will validate that no user is registered with the same email address and also validate password. After validation is confirmed we store the user-provided information in the users’ table and alert the user that registration was successful.
2) Building a Login System
In this part, we will create a login form to allow users to access the restricted area of the system. In our case, the restricted area is a welcome page which we will cover in the next part.
Step 1: Creating a Login Form in HTML
Below is the Login Form in HTML. Paste it in a file named login.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-12">
<h2>Login</h2>
<p>Please fill in your email and password.</p>
<form action="" method="post">
<div class="form-group">
<label>Email Address</label>
<input type="email" name="email" class="form-control" required />
</div>
<div class="form-group">
<label>Password</label>
<input type="password" name="password" class="form-control" required>
</div>
<div class="form-group">
<input type="submit" name="submit" class="btn btn-primary" value="Submit">
</div>
<p>Don't have an account? <a href="register.php">Register here</a>.</p>
</form>
</div>
</div>
</div>
</body>
</html>
The output of the above code will look like this
Step 2: Creating a Login System in PHP
After creating the login form in HTML, we will write a code to validate login credentials. On form submit we will check that the email and password are filled. If they filled then we will execute a SELECT
query to find the record in a database on the basis of email and password. If any record found, then we will store the "userID"
in session and the user is redirected to the welcome.php file, otherwise, the user is alerted with an error message.
Let’s replace the following code in the login.php file.
<?php
require_once "config.php";
require_once "session.php";
$error = '';
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['submit'])) {
$email = trim($_POST['email']);
$password = trim($_POST['password']);
// validate if email is empty
if (empty($email)) {
$error .= '<p class="error">Please enter email.</p>';
}
// validate if password is empty
if (empty($password)) {
$error .= '<p class="error">Please enter your password.</p>';
}
if (empty($error)) {
if($query = $db->prepare("SELECT * FROM users WHERE email = ?")) {
$query->bind_param('s', $email);
$query->execute();
$row = $query->fetch();
if ($row) {
if (password_verify($password, $row['password'])) {
$_SESSION["userid"] = $row['id'];
$_SESSION["user"] = $row;
// Redirect the user to welcome page
header("location: welcome.php");
exit;
} else {
$error .= '<p class="error">The password is not valid.</p>';
}
} else {
$error .= '<p class="error">No User exist with that email address.</p>';
}
}
$query->close();
}
// Close connection
mysqli_close($db);
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-12">
<h2>Login</h2>
<p>Please fill in your email and password.</p>
<?php echo $error; ?>
<form action="" method="post">
<div class="form-group">
<label>Email Address</label>
<input type="email" name="email" class="form-control" required />
</div>
<div class="form-group">
<label>Password</label>
<input type="password" name="password" class="form-control" required>
</div>
<div class="form-group">
<input type="submit" name="submit" class="btn btn-primary" value="Submit">
</div>
<p>Don't have an account? <a href="register.php">Register here</a>.</p>
</form>
</div>
</div>
</div>
</body>
</html>
3) Creating a Welcome Page
Below is the code for the welcome.php file. Users will be redirected to this page after a successful login process. We have added some code at the top of the page to check if the user is not logged in, then redirect the user to the login page.
Let’s create a welcome.php file and paste the following code in it.
<?php
// start the session
session_start();
// Check if the user is not logged in, then redirect the user to login page
if (!isset($_SESSION["userid"]) || $_SESSION["userid"] !== true) {
header("location: login.php");
exit;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Welcome <?php echo $_SESSION["name"]; ?></title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-12">
<h1>Hello, <strong><?php echo $_SESSION["name"]; ?></strong>. Welcome to demo site.</h1>
</div>
<p>
<a href="logout.php" class="btn btn-secondary btn-lg active" role="button" aria-pressed="true">Log Out</a>
</p>
</div>
</div>
</body>
</html>
4) The Logout script
Finally, Let’s create a logout.php file with the following code in it.
<?php
// Start the session
session_start();
// Destroy the session.
if (session_destroy()) {
// redirect to the login page
header("Location: login.php");
exit;
}
?>
Once the user clicks on the Log Out link, the above script, will be called to destroy the session and redirect user to the login.php file.
Conclusion
In this tutorial, I explained how you can create a Login System using HTML, PHP and MySQL. Once you understand how simple it is to create a login system you can add other features like reset password, forgot password, verify email address, edit user’s profile, etc.
Из песочницы, PHP, HTML
Рекомендация: подборка платных и бесплатных курсов PR-менеджеров — https://katalog-kursov.ru/
Здравствуйте! Облазил множество ресурсов, но так и не нашел ни одной полезной, правильной, легкой и работающей статьи на тему “Как сделать Вход и Регистрацию на сайте”.
Что будет использоваться? Использоваться будет только HTML + Bootstrap, а также PHP + MySQL.
Какие возможности будут у данной формы? Пользователь сможет зарегистрироваться, войти, а также выйти из своего аккаунта, пароль будет шифроваться, будут обрабатываться некоторые ошибки, остальное пишите сами. Приступим!
Создание Базы Данных
Я буду работать на локальном хостинге, а именно на OpenServer. Для того чтобы создать базу данных, необходимо войти в phpmyadmin, затем нажать на кнопку «Создать Базу Данных».
Далее вводите название своей базы данных, у меня это будет — «register-bd».
Дальше создаем таблицу, называем таблицу users, в ней будет 4 столбца.
Заполнение таблицы
Дальше нам нужно ввести переменные в базу данных. Первая переменная — id. Это будет уникальный айди пользователя. В поле имя вводим «id»; тип — INT, так как это буду просто целые числа; Длина/Значения — 11, таким образом это будет 11-ти значное число, думаю нам его должно хватить; Атрибуты — «UNSIGNED» — числа только положительные; Индекс — «UNIQUE», во всплывающем окне пишем — «id», то есть каждый следующий айди будет больше на 1, чем предыдущий; A_I — ставим галочку.
Следующая строка — login, VARCHAR, 50, сравнение — utf_8_general_ci. Следующие поля это login и pass, применяем все тоже самое. Далее Тип таблиц выбираем: MyISAM и нажимаем сохранить. В итоге у Вас все должно выглядеть вот так:
Разработка дизайна формы
Теперь быстро верстаем форму для авторизации и регистрации на Bootstrap, называем файл index.php, думаю в этом ничего сложного нету, поэтому просто оставляю код здесь:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<title>Вход/Регистрация</title>
</head>
<body>
<div class="container mt-4">
<div class="row">
<div class="col">
<h1>Форма регистрации</h1>
<form action="check.php" method="post">
<input type="text" name="login" class="form-control" id="login" placeholder="Логин"><br>
<input type="text" name="name" class="form-control" id="name" placeholder="Имя"><br>
<input type="password" name="pass" class="form-control" id="pass" placeholder="Пароль"><br>
<button class="btn btn-success">Зарегистрироваться</button><br>
</form>
</div>
<div class="col">
<h1>Форма регистрации</h1>
<form action="auth.php" method="post">
<input type="text" name="login" class="form-control" id="login" placeholder="Логин"><br>
<input type="password" name="pass" class="form-control" id="pass" placeholder="Пароль"><br>
<button class="btn btn-success">Авторизоваться</button><br>
</form>
</div>
</div>
</div>
</body>
</html>
Регистрация
check.php
Создаем файл check.php.
Для начала Мы получаем все значения из полей регистрации и убираем все ненужные теги и пробелы, а то мало ли, что там пользователь может написать.
<?php
$login = filter_var(trim($_POST['login']), FILTER_SANITIZE_STRING); // Удаляет все лишнее и записываем значение в переменную //$login
$name = filter_var(trim($_POST['name']), FILTER_SANITIZE_STRING);
$pass = filter_var(trim($_POST['pass']), FILTER_SANITIZE_STRING); ?>
Дальше мы проверяем логин и имя на длину. Если длина меньше 5, мы выводим сообщение об ошибке.
if(mb_strlen($login) < 5 || mb_strlen($login) > 90){
echo "Недопустимая длина логина";
exit();
}
else if(mb_strlen($name) < 5){
echo "Недопустимая длина имени.";
exit();
} // Проверяем длину имени
?>
Теперь мы хешируем пароль, с помощью md5(), и добавляем свои какие-то рандомные символы, для усложнения пароля, у меня это будет: «thisiforhabr»
$pass = md5($pass."thisisforhabr"); // Создаем хэш из пароля
Далее мы подключаемся к Базе Данных, первый параметр это хост, второй — имя пользователя, третье — пароль и четвертое это название БД:
$mysql = new mysqli('localhost', 'root', '', 'register-bd');
Затем мы проверяем логин на совпадение, если в Базе Данных система находит такой же логин — сообщаем об ошибке.
$result1 = $mysql->query("SELECT * FROM `users` WHERE `login` = '$login'");
$user1 = $result1->fetch_assoc(); // Конвертируем в массив
if(!empty($user1)){
echo "Данный логин уже используется!";
exit();
}
Что в этом коде происходит ?
В первой строке идет язык SQL, мы говорим базе данных отбирать из таблицы users, login, который совпадает с логином, который ввел пользователь, дальше создаем массив и если массив не пустой, значит система что-то нашла, из этого выходит что такой логин уже зарегистрирован — уведомляем пользователя об этом.
Если все в порядке — регистрируем в Базе Данных пользователя и закрываем соединение:
$mysql->query("INSERT INTO `users` (`login`, `pass`, `name`)
VALUES('$login', '$pass', '$name')");
$mysql->close();
Авторизация
auth.php
Теперь приступим к авторизации, все так же получаем данные из полей, только имя нам теперь не нужно:
$login = filter_var(trim($_POST['login']), FILTER_SANITIZE_STRING);
$pass = filter_var(trim($_POST['pass']), FILTER_SANITIZE_STRING);
Шифруем пароль, подключаемся к базе данных, создаем массив и проверяем в БД на совпадение пароля и логина — если совпадения находит, то одобряем пользователю вход, если нет — выводим сообщение об ошибке:
if(count($user) == 0){
echo "Такой пользователь не найден.";
exit();
}
else if(count($user) == 1){
echo "Логин или праоль введены неверно";
exit();
}
setcookie('user', $user['name'], time() + 3600, "/");
$mysql->close();
header('Location: page.html');
header… Означает что пользователя, если авторизация прошла успешно, будет перебрасывать на страницу page.html. Поэтому создаем страницу page.html и пишем просто ссылку:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<h1>Привет!</h1>
<a href="exit.php">Что бы выйти нажмите по ссылке.</a>
</body>
</html>
Выход
Для того чтобы пользователь вышел — нам всего лишь нужно очистить куки, создаем файл exit.php и в нем пишем:
<?php
setcookie('user', $user['name'], time() - 3600, "/");
header('Location: /');
?>
На этом у меня все, если у кого-то будет что-то не получаться или не работать — пишите в комментарии! Я постараюсь всем ответить и по возможности помочь.
Итоговый код всех файлов
index.php
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<title>Вход/Регистрация</title>
</head>
<body>
<div class="container mt-4">
<div class="row">
<div class="col">
<h1>Форма регистрации</h1>
<form action="check.php" method="post">
<input type="text" name="login" class="form-control" id="login" placeholder="Логин"><br>
<input type="text" name="name" class="form-control" id="name" placeholder="Имя"><br>
<input type="password" name="pass" class="form-control" id="pass" placeholder="Пароль"><br>
<button class="btn btn-success">Зарегистрироваться</button><br>
</form>
</div>
<div class="col">
<h1>Форма регистрации</h1>
<form action="auth.php" method="post">
<input type="text" name="login" class="form-control" id="login" placeholder="Логин"><br>
<input type="password" name="pass" class="form-control" id="pass" placeholder="Пароль"><br>
<button class="btn btn-success">Авторизоваться</button><br>
</form>
</div>
</div>
</div>
</body>
</html>
check.php
<?php
$login = filter_var(trim($_POST['login']), FILTER_SANITIZE_STRING); // Удаляет все лишнее и записываем значение в переменную //$login
$name = filter_var(trim($_POST['name']), FILTER_SANITIZE_STRING);
$pass = filter_var(trim($_POST['pass']), FILTER_SANITIZE_STRING);
if(mb_strlen($login) < 5 || mb_strlen($login) > 90){
echo "Недопустимая длина логина";
exit();
}
else if(mb_strlen($name) < 5){
echo "Недопустимая длина имени.";
exit();
} // Проверяем длину имени
$pass = md5($pass."thisisforhabr"); // Создаем хэш из пароля
$mysql = new mysqli('localhost', 'root', '', 'register-bd');
$result1 = $mysql->query("SELECT * FROM `users` WHERE `login` = '$login'");
$user1 = $result1->fetch_assoc(); // Конвертируем в массив
if(!empty($user1)){
echo "Данный логин уже используется!";
exit();
}
header('Location: /');
exit();
?>
auth.php
<?php
$login = filter_var(trim($_POST['login']), FILTER_SANITIZE_STRING);
$pass = filter_var(trim($_POST['pass']), FILTER_SANITIZE_STRING);
$pass = md5($pass."forhktkntuhpi"); // Создаем хэш из пароля
$mysql = new mysqli('localhost', 'root', '', 'register-bd');
$result = $mysql->query("SELECT * FROM `users` WHERE `login` = '$login' AND `pass` = '$pass'");
$user = $result->fetch_assoc(); // Конвертируем в массив
if(count($user) == 0){
echo "Такой пользователь не найден.";
exit();
}
else if(count($user) == 1){
echo "Логин или праоль введены неверно";
exit();
}
setcookie('user', $user['name'], time() + 3600, "/");
$mysql->close();
header('Location: page.html');
?>
page.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<h1>Привет!</h1>
<a href="exit.php">Что бы выйти нажмите по ссылке.</a>
</body>
</html>
exit.php
<?php
setcookie('user', $user['name'], time() - 3600, "/");
header('Location: /');
?>
Возможно использовать функцию header() для
отправки сообщения "Authentication Required"
браузеру, заставив его показать окошко для ввода логина и пароля.
Как только пользователь заполнит логин и пароль, ссылка, содержащая
PHP-скрипт будет вызвана ещё раз с
предопределёнными переменными
PHP_AUTH_USER, PHP_AUTH_PW
и AUTH_TYPE, установленными в логин, пароль
и тип аутентификации соответственно. Эти предопределённые
переменные хранятся в массиве $_SERVER.
Поддерживаются только: «Basic» и «Digest». Подробнее
смотрите функцию header().
Пример фрагмента скрипта, который вынуждает клиента авторизоваться для
просмотра страницы:
Пример #1 Пример Basic HTTP-аутентификации
<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
echo 'Текст, отправляемый в том случае,
если пользователь нажал кнопку Cancel';
exit;
} else {
echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";
echo "<p>Вы ввели пароль {$_SERVER['PHP_AUTH_PW']}.</p>";
}
?>
Пример #2 Пример Digest HTTP-аутентификации
Это пример реализации простого скрипта Digest HTTP-аутентификации.
За подробностями обращайтесь к » RFC 2617.
<?php
$realm = 'Запретная зона';//user => password
$users = array('admin' => 'mypass', 'guest' => 'guest');
if (empty(
$_SERVER['PHP_AUTH_DIGEST'])) {
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Digest realm="'.$realm.
'",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');
die(
'Текст, отправляемый в том случае, если пользователь нажал кнопку Cancel');
}// анализируем переменную PHP_AUTH_DIGEST
if (!($data = http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) ||
!isset($users[$data['username']]))
die('Неправильные данные!');// генерируем корректный ответ
$A1 = md5($data['username'] . ':' . $realm . ':' . $users[$data['username']]);
$A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);
$valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);
if (
$data['response'] != $valid_response)
die('Неправильные данные!');// все хорошо, логин и пароль верны
echo 'Вы вошли как: ' . $data['username'];// функция разбора заголовка http auth
function http_digest_parse($txt)
{
// защита от отсутствующих данных
$needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
$data = array();
$keys = implode('|', array_keys($needed_parts));preg_match_all('@(' . $keys . ')=(?:(['"])([^2]+?)2|([^s,]+))@', $txt, $matches, PREG_SET_ORDER);
foreach (
$matches as $m) {
$data[$m[1]] = $m[3] ? $m[3] : $m[4];
unset($needed_parts[$m[1]]);
}
return
$needed_parts ? false : $data;
}
?>
Замечание:
Замечание касательно совместимостиБудьте особенно внимательны при указании HTTP-заголовков. Для того, чтобы
гарантировать максимальную совместимость с наибольшим количеством
различных клиентов, слово «Basic» должно быть написано с большой буквы «B»,
регион (realm) должен быть взят в двойные (не одинарные!) кавычки,
и ровно один пробел должен предшествовать коду 401 в заголовке
HTTP/1.0 401. Параметры аутентификации должны
разделяться запятыми, как это было показано в примере Digest
аутентификации выше.
Вместо простого отображения на экране переменных PHP_AUTH_USER
и PHP_AUTH_PW, вам, возможно, понадобится
проверить их корректность. Используйте для этого запрос к базе
данных или поиск пользователя в dbm-файле.
Вы можете пронаблюдать особенности работы браузера Internet Explorer.
Он очень требователен к параметру передаваемых заголовков. Трюк с указанием
заголовка WWW-Authenticate перед отправкой статуса
HTTP/1.0 401
пока что работает для него.
Замечание:
Замечание касательно конфигурацииPHP использует указание директивы
AuthType
для
указания того, используется внешняя аутентификация или нет.
Следует заметить, что все вышесказанное не предотвращает похищения паролей к
страницам, требующим авторизацию, кем-либо, кто контролирует страницы без
авторизации, расположенные на том же сервере.
И Netscape Navigator и Internet Explorer очищают кеш аутентификации
текущего окна для заданного региона (realm) при получении от сервера статуса 401.
Это может использоваться для реализации принудительного выхода пользователя
и повторного отображения диалогового окна для ввода имени пользователя и
пароля. Некоторые разработчики используют это для ограничения авторизации по
времени или для предоставления кнопки «Выход».
Пример #3 Пример HTTP-аутентификации с принудительным вводом новой пары логин/пароль
<?php
function authenticate() {
header('WWW-Authenticate: Basic realm="Test Authentication System"');
header('HTTP/1.0 401 Unauthorized');
echo "Вы должны ввести корректный логин и пароль для получения доступа к ресурсу n";
exit;
}
if (!isset(
$_SERVER['PHP_AUTH_USER']) ||
($_POST['SeenBefore'] == 1 && $_POST['OldAuth'] == $_SERVER['PHP_AUTH_USER'])) {
authenticate();
} else {
echo "<p>Добро пожаловать: " . htmlspecialchars($_SERVER['PHP_AUTH_USER']) . "<br />";
echo "Предыдущий логин: " . htmlspecialchars($_REQUEST['OldAuth']);
echo "<form action='' method='post'>n";
echo "<input type='hidden' name='SeenBefore' value='1' />n";
echo "<input type='hidden' name='OldAuth' value="" . htmlspecialchars($_SERVER['PHP_AUTH_USER']) . "" />n";
echo "<input type='submit' value='Авторизоваться повторно' />n";
echo "</form></p>n";
}
?>
Это поведение не регламентируется стандартами HTTP Basic
-аутентификации,
следовательно, вы не должны зависеть от этого. Тестирование браузера Lynx
показало, что Lynx
не очищает кеш авторизации при получении от сервера
статуса 401, и, нажав последовательно «Back», а затем «Forward» возможно
открыть такую страницу, при условии, что требуемые атрибуты авторизации не изменились.
Однако, пользователь может нажать клавишу '_'
для очистки кеша аутентификации.
Для того, чтобы добиться корректной работы HTTP-аутентификации в IIS сервере с
CGI версией PHP, вы должны отредактировать
конфигурационную настройку IIS под названием «Directory Security
«.
Щёлкните на надписи «Edit
» и установите опцию
«Anonymous Access
«,
все остальные поля должны остаться неотмеченными.
Замечание:
Замечание касательно IIS:
Для того, чтобы HTTP-аутентификация корректно работала в IIS, в конфигурации
PHP-опция cgi.rfc2616_headers должна
быть установлена значением0
(значение по умолчанию).
derkontrollfreak+9hy5l at gmail dot com ¶
8 years ago
Workaround for missing Authorization header under CGI/FastCGI Apache:
SetEnvIf Authorization .+ HTTP_AUTHORIZATION=$0
Now PHP should automatically declare $_SERVER[PHP_AUTH_*] variables if the client sends the Authorization header.
kazakevichilya at gmail dot com ¶
10 years ago
In case of CGI/FastCGI you would hot be able to access PHP_AUTH* info because CGI protocol does not declare such variables (that is why their names start from PHP) and server would not pass them to the interpreter. In CGI server should authenticate user itself and pass REMOTE_USER to CGI script after it.
So you need to "fetch" request headers and pass them to your script somehow.
In apache you can do it via environment variables if mod_env is installed.
Following construction in .htaccess copies request header "Authorization" to the env variable PHP_AUTH_DIGEST_RAW
SetEnvIfNoCase ^Authorization$ "(.+)" PHP_AUTH_DIGEST_RAW=$1
You can now access it via $_ENV.
Do not forget to strip auth type ("Digest" in my case) from your env variable because PHP_AUTH_DIGEST does not have it.
If mod_env is not installed you probably have mod_rewrite (everyone has it because of "human readable URLs").
You can fetch header and pass it as GET parameter using rewrite rule:
RewriteRule ^.*$ site.php?PHP_AUTH_DIGEST_RAW=%{HTTP:Authorization} [NC,L]
Here HTTP request header Authorization would be acessible as PHP_AUTH_DIGEST_RAW via $_GET.
---
If you use ZF you probably use Zend_Auth_Adapter_Http to auth user.
It takes Authorization info using "Zend_Controller_Request::getHeader"
This method uses apache_request_header which is likely not to be accessible in old CGI/FastCGI installations or _$_SERVER['HTTP_<HeaderName>] , so you need to put your authentication data, obtained via _GET or ENV to
_$_SERVER['HTTP_AUTHORIZATION'].
It will make ZF work transparently with you solution and I believe any other framework should work also
webmaster at kratia dot com ¶
16 years ago
This is the simplest form I found to do a Basic authorization with retries.
<?php
$valid_passwords
= array ("mario" => "carbonell");
$valid_users = array_keys($valid_passwords);$user = $_SERVER['PHP_AUTH_USER'];
$pass = $_SERVER['PHP_AUTH_PW'];$validated = (in_array($user, $valid_users)) && ($pass == $valid_passwords[$user]);
if (!
$validated) {
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
die ("Not authorized");
}// If arrives here, is a valid user.
echo "<p>Welcome $user.</p>";
echo "<p>Congratulation, you are into the system.</p>";?>
admin at isprohosting dot com ¶
16 years ago
There are .htaccess which actually works for us (cPanel + phpsuexec) unless others failed. Perhaps it may help someone.
# PHP (CGI mode) HTTP Authorization with ModRewrite:
RewriteEngine on
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule ^(.*) - [E=HTTP_AUTHORIZATION:%1]
Then you need small piece of php code to parse this line and then everything will work like with mod_php:
if (isset($_SERVER['HTTP_AUTHORIZATION']))
{
$ha = base64_decode( substr($_SERVER['HTTP_AUTHORIZATION'],6) );
list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) = explode(':', $ha);
unset $ha;
}
Enjoy!
john_2232 at gmail dot com ¶
7 years ago
Here is my attempt to create a digest authentication class that will log the user in and out without using a cookie,session,db,or file. At the core is this simple code to parse the digest string into variables works for several browsers.
<?php
// explode the digest with multibrowser support by Tony Wyatt 21jun07
public function explodethedigest($instring) {
$quote = '"';
$equal = '=';
$comma = ',';
$space = ' ';
$a = explode( $comma, $instring);
$ax = explode($space, $a[0]);
$b = explode( $equal, $ax[1], 2);
$c = explode( $equal, $a[1], 2);
$d = explode( $equal, $a[2], 2);
$e = explode( $equal, $a[3], 2);
$f = explode( $equal, $a[4], 2);
$g = explode( $equal, $a[5], 2);
$h = explode( $equal, $a[6], 2);
$i = explode( $equal, $a[7], 2);
$j = explode( $equal, $a[8], 2);
$k = explode( $equal, $a[9], 2);
$l = explode( $equal, $a[10], 2);
$parts = array(trim($b[0])=>trim($b[1], '"'), trim($c[0])=>trim($c[1], '"'), trim($d[0])=>trim($d[1], '"'), trim($e[0])=>trim($e[1], '"'), trim($f[0])=>trim($f[1], '"'), trim($g[0])=>trim($g[1], '"'), trim($h[0])=>trim($h[1], '"'), trim($i[0])=>trim($i[1], '"'), trim($j[0])=>trim($j[1], '"'), trim($k[0])=>trim($k[1], '"'), trim($l[0])=>trim($l[1], '"'));
return
$parts;
}
?>
Give it a try at http://www.creativetheory.ca/ /tests/ta1.php Log in with user test password pass or user guest password guest. Go to page two for links to the code. Comments, ideas, suggestions, or critique welcome.
php at cscott dot net ¶
18 years ago
roychri at php dot net ¶
16 years ago
For PHP with CGI, make sure you put the rewrite rule above any other rewrite rule you might have.
In my case, I put this at the top of the .htaccess (below RewriteEngine On):
RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization}]
My symptom was that the REMOTE_USER (or REDIRECT_REMOTE_USER in my case) was not being set at all.
The cause: I had some other RewriteRule that was kickin in and was set as LAST rule.
I hope this helps.
Carlos ¶
5 years ago
Simpler WorkAround for missing Authorization header under CGI/FastCGI available in Apache HTTP Server 2.4.13 and later
CGIPassAuth On
Please don't enable Authorization header with Basic Authentication, is very insecure.
Robb_Bean at gmx dot net ¶
9 years ago
In the german example #2 (digest), the <?php $realm = "Geschützter Bereich"; ?>. As far as I have tested the umlaut ü is problematic, resulting in an password enter infinity loop. In my case it was written in UTF-8. So I suggest using only plain ASCII characters for the realm.
Nicolas Merlet — admin(at)merletn.org ¶
16 years ago
Be careful using http digest authentication (see above, example 34.2) if you have to use the 'setlocale' function *before* validating response with the 'http_digest_parse' function, because there's a conflict with w in the pattern of 'preg_match_all' function :
In fact, as w is supposed to be any letter or digit or the underscore character, you must not forgot that this may vary depending on your locale configuration (eg. it accepts accented letters in french)...
Due to this different pattern interpretation by the 'preg_match_all' function, the 'http_digest_parse' function will always return a false result if you have modified your locale (I mean if your locale accepts some extended characters, see http://fr.php.net/manual/en/reference.pcre.pattern.syntax.php for further information).
IMHO, I suggest you not to use setlocale before having your authentication completed...
PS : Here's a non-compatible setlocale declaration...
setlocale ( LC_ALL, 'fr_FR', 'fr', 'FR', 'french', 'fra', 'france', 'French', 'fr_FR.ISO8859-1' ) ;
gbelyh at gmail dot com ¶
15 years ago
Back to the autherisation in CGI mode. this is the full working example:
# Create the .htaccess file with following contents:
# also you can use the condition (search at this page)
RewriteEngine on
RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization},L]
# In the beginning the script checking the authorization place the code:
$userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"],6)) ;
$userpass = explode(":", $userpass);
if ( count($userpass) == 2 ){
#this part work not for all.
#print_r($userpass);die; #<- this can help find out right username and password
list($name, $password) = explode(':', $userpass);
$_SERVER['PHP_AUTH_USER'] = $name;
$_SERVER['PHP_AUTH_PW'] = $password;
}
xsanychx at mail dot ru ¶
10 years ago
New auth:
<?php
$login = 'test_login';
$pass = 'test_pass';
if((
$_SERVER['PHP_AUTH_PW']!= $pass || $_SERVER['PHP_AUTH_USER'] != $login)|| !$_SERVER['PHP_AUTH_USER'])
{
header('WWW-Authenticate: Basic realm="Test auth"');
header('HTTP/1.0 401 Unauthorized');
echo 'Auth failed';
exit;
}
?>
Yuriy ¶
14 years ago
Good day.
Sorry for my english.
This example shows programming "LOGIN", "LOGOUT" and "RE-LOGIN".
This script must use in the protected pages.
For work this script the browser address string must be following:
"http://localhost/admin/?login" - for Login,
"http://localhost/admin/?logout" - for Logout,
"http://localhost/admin/?logout&login" - for Re-Login.
<?php
session_start();$authorized = false;# LOGOUT
if (isset($_GET['logout']) && !isset($_GET["login"]) && isset($_SESSION['auth']))
{
$_SESSION = array();
unset($_COOKIE[session_name()]);
session_destroy();
echo "logging out...";
}# checkup login and password
if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW']))
{
$user = 'test';
$pass = 'test';
if (($user == $_SERVER['PHP_AUTH_USER']) && ($pass == ($_SERVER['PHP_AUTH_PW'])) && isset($_SESSION['auth']))
{
$authorized = true;
}
}# login
if (isset($_GET["login"]) && !$authorized ||
# relogin
isset($_GET["login"]) && isset($_GET["logout"]) && !isset($_SESSION['reauth']))
{
header('WWW-Authenticate: Basic Realm="Login please"');
header('HTTP/1.0 401 Unauthorized');
$_SESSION['auth'] = true;
$_SESSION['reauth'] = true;
echo "Login now or forever hold your clicks...";
exit;
}
$_SESSION['reauth'] = null;
?>
<h1>you have <? echo ($authorized) ? (isset($_GET["login"]) && isset($_GET["logout"]) ? 're' : '') : 'not '; ?>logged!</h1>
Louis ¶
16 years ago
I couldn't get authentication to work properly with any of the examples. Finally, I started from ZEND's tutorial example at:
http://www.zend.com/zend/tut/authentication.php?article=authentication (validate using .htpasswd) and tried to deal with the additional cases. My general conclusion is that changing the realm is the only reliable way to cause the browser to ask again, and I like to thank the person who put that example in the manual, as it got me on the right path. No matter what, the browser refuses to discard the values that it already has in mind otherwise. The problem with changing the realm, of course, is that you don't want to do it within a given session, else it causes a new request for a password. So, here goes, hopefully the spacing isn't too messed up by the cut'n'paste.
I spent the better part of a day getting this to work right. I had a very hard time thinking through what the browser does when it encounters an authentication request: seems to me that it tries to get the password, then reloads the page... so the HTML doesn't get run. At least, this was the case with IE, I haven't tested it with anything else.
<?php
session_start() ;
if (!isset($_SESSION['realm'])) {
$_SESSION['realm'] = mt_rand( 1, 1000000000 ).
" SECOND level: Enter your !!!COMPANY!!! password.";header( "WWW-Authenticate: Basic realm=".$_SESSION['realm'] );// Below here runs HTML-wise only if there isn't a $_SESSION,
// and the browser *can't* set $PHP_AUTH_USER... normally
// the browser, having gotten the auth info, runs the page
// again without getting here.
// What I'm basically getting to is that the way to get
// here is to escape past the login screen. I tried
// putting a session_destroy() here originally, but the
// problem is that the PHP runs regardless, so the
// REFRESH seems like the best way to deal with it.
echo "<meta http-equiv="REFRESH"
content="0;url=index.php">" ;
exit;
}
if (
$_POST['logout'] == "logout") {
session_destroy() ;
header('Location: comeagain.php');
exit ;
}// "standard" authentication code here, from the ZEND tutorial above.comeagain.php is as follows:
<?
session_start();
unset($_SESSION['realm']);
session_destroy();
echo "<html><head><title>Logged Out</title><h1>Logout Page</h1><body>" ;
echo "You have successfully logged out of TOGEN";
echo " at ".date("h:m:s")." on ".date("d F Y") ;
echo "<p><a href="index.php">Login Again</a>" ;
echo "</body></html>" ;
?>
The idea is to be able to trash the session (and thus reset the realm) without prompting the browser to ask again... because it has been redirected to logout.php.
With this combination, I get things to work. Just make sure not to have apache run htpasswd authentication at the same time, then things get really weird :-).
jake22 at gmail dot com ¶
7 years ago
I came up with another approach to work around the problem of browsers caching WWW authentication credentials and creating logout problems. While most browsers have some kind of way to wipe this information, I prefer having my website to take care of the task instead of relying on the user's sanity.
Even with Lalit's method of creating a random realm name, it was still possible to get back into the protected area using the back button in Firefox, so that didn't work. Here's my solution:
Since browsers attach the credentials to specific URLs, use virtual paths where a component of the path is actually a PHP script, and everything following it is part of the URI, such as:
http://velocitypress.ca/some_dir/login.php/auth/8f631b92/
By choosing a different number for the last component of the URL, browsers can be tricked into thinking that they are dealing with a completely different website, and thus prompting the user for credentials again.
Note that using a random, unrestricted number will still allow the user to hit the back button to get back into the page. You should keep track of this number in a server-side file or database and regenerate it upon each successful login, so that the last number(s) become invalid. Using an invalid number might result in a 403 response or, depending on how you feel that day, a 302 to a nasty website.
Care should be taken when linking from the page generated in this case, since relative links will be relative to the virtual and non-existant directory rather than the true script directory.
Anonymous ¶
13 years ago
The regex in http_digest_parse from Example #2 does not work for me (PHP 5.2.6), because back references are not allowed in a character class. This worked for me:
<?php// function to parse the http auth header
function http_digest_parse($txt)
{
// protect against missing data
$needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
$data = array();preg_match_all('@(w+)=(?:(?:'([^']+)'|"([^"]+)")|([^s,]+))@', $txt, $matches, PREG_SET_ORDER);
foreach (
$matches as $m) {
$data[$m[1]] = $m[2] ? $m[2] : ($m[3] ? $m[3] : $m[4]);
unset($needed_parts[$m[1]]);
}
return
$needed_parts ? false : $data;
}?>
vog at notjusthosting dot com ¶
11 years ago
You shouldn't use the "last" ("L") directive in the RewriteRule! This will prevent all further rewrite rules to be skipped whenever a Basic or Digest Auth is given, which is almost certainly not what you want.
So the following lines are sufficient for the .htaccess (or httpd.conf) file:
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
spam at angstzustaen dot de ¶
1 year ago
public function loginUser(){
$username = filter_var($_GET['username'],FILTER_SANITIZE_STRING);
$pw = filter_var($_GET['pw'],FILTER_SANITIZE_STRING);
$row = $this->userModel->selectUser($username);
if (password_verify($pw,$row['pw'])){
$_SESSION["userId"] = $row['id'];
$this->isLogin();
} else{
new Msg(true,"Benutzername und Passwort stimmen nicht überein!");
}
}
A short example for an user Login
patrick dot moire at socopa dot fr ¶
2 years ago
Samples Login / Logout script
login.php :
<?php// Initisalition
if ($_COOKIE["SESSION"]=='') {
setcookie("SESSION", 'AUTH', 0,'/'); // Identification perdu (time-out ou logoff)
} else if ($_SERVER['PHP_AUTH_USER']!='' && $_COOKIE["USER_SESSION"]=='') {
$_SERVER['PHP_AUTH_USER'] = '';
}// Controle identification à la base
$ident = executeSQL("SELECT * FROM UTILISATEURS WHERE upper(IDENTIFIANT)=Upper('".$_SERVER['PHP_AUTH_USER']."')");
if ($_SERVER['PHP_AUTH_USER']!='' && strtoupper($ident['IDENTIFIANT'])==strtoupper($_SERVER['PHP_AUTH_USER']) && $ident['MOT_DE_PASSE']==$_SERVER['PHP_AUTH_PW']) {
$user = $_SERVER['PHP_AUTH_USER'];
setcookie("USER_SESSION", $user, time()+300,'/'); // 5 Minutes !
// Mot de passe incorecte : demande identification
} else {
setcookie("SESSION", '', 1,'/');
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
die;
}?>
<html>
<body >
Bonjour <?php echo $ident['NOM'].' '.$ident['PRENOM']; ?>
<br>
<br>
<a href="http://logout.php">Deconnexion</a>
</body>
</html>
logout.php :
<?php
setcookie("USER_SESSION", '', 1,'/');
header('Location: http://login.php');
?>
bitman at bitworks dot de ¶
1 year ago
the alternative text should contain the complete text af a (small) valid HTML-Ressource. It also can contain link relations to CSS.
dan223 at gmail dot com ¶
7 years ago
A simple script for SSL Client Certificate authentication with a basic authentication fall-back. I use this on my site using LDAP server to check username/passwords and client certificate to user mapping.
<?
// Check if and how we are authenticated
if ($_SERVER['SSL_CLIENT_VERIFY'] != "SUCCESS") { // Not using a client certificate
if ((!$_SERVER['PHP_AUTH_USER']) && (!$_SERVER['PHP_AUTH_PW'])) { // Not logged in using basic authentication
authenticate(); // Send basic authentication headers
}
}
if ($_SERVER['SSL_CLIENT_S_DN_CN'] != "chris") { // Check CN name of cert
if (!(($_SERVER['PHP_AUTH_USER'] == "test") && ($_SERVER['PHP_AUTH_PW'] == "123"))) { // Check username and password
authenticate(); // Send basic authentication headers because username and/or password didnot match
}
}
phpinfo();
// Call authentication display
function authenticate() {
Header("WWW-Authenticate: Basic realm=Website");
Header("HTTP/1.0 401 Unauthorized");
error401();
exit;
}
?>
See my website (http://velocitypress.ca/index.php?page=/manuals/) for more details on client certificate with Apache and PHP.
Ome Ko ¶
12 years ago
a link to http://logout:logout@<?=$_SERVER['HTTP_HOST'];?>/SECRET/ would force a fresh login for the /SECRET directory if no user logout with password logout exists.
[NOTE BY danbrown AT php DOT net: The following note was added by "Anonymous" on 01-APR-2010 (though we presume it's not an April Fool's Day joke).]
this logout method does not work 100% anymore, because of another bulls**t from M$:
http://support.microsoft.com/kb/834489
SlamJam ¶
16 years ago
I used Louis example (03-Jun-2006) and it works well for me (thanks).
However, I added some lines, to make sure, the user does only get the Authentification-Window a few times:
<?php
$realm = mt_rand( 1, 1000000000)."@YourCompany";
$_SESSION['realm'] = $realm;
// In the beginning, when the realm ist defined:
$_SESSION['CountTrials'] = 1;
?>
And then when it comes to check the authentification (ZEND-Tutorial):
<?php
// Not more than 3 Trials
if (!$auth) {
$_SESSION['CountTrials']++;
if ($_SESSION['CountTrials'] == 4) {
session_destroy() ;
header('Location: noentry.php');
exit ;
} else {
header("WWW-Authenticate: Basic realm=".$_SESSION['realm']);
header("HTTP/1.0 401 Unauthorized");
echo 'Authorization Required.';
exit;
}
} else {
echo '<P>You are authorized!</P>';
}
?>
noentry.php is slightely different from comeagain.php.
sjeffrey at inquesis dot com ¶
21 years ago
To get it to work with IIS try using this code before setting your "$auth = 0" and the "if (isset($PHP_AUTH_USER) && isset($PHP_AUTH_PW))"
<?php
//////////////////////////////////////////
if ($PHP_AUTH_USER == "" && $PHP_AUTH_PW == "" && ereg("^Basic ", $HTTP_AUTHORIZATION))
{
list($PHP_AUTH_USER, $PHP_AUTH_PW) =
explode(":", base64_decode(substr($HTTP_AUTHORIZATION, 6)));
}
//////////////////////////////////////////
?>
It worked for me on IIS 5 and PHP 4 in ISAPI
Lars Stecken ¶
15 years ago
To anybody who tried the digest example above and didn't get it to work.
For me the problem seemed to be the deprecated use of '' (backslash) in the regex instead of the '$' (Dollar) to indicate a backreference. Also the results have to be trimmed off the remaining double and single quotes.
Here's the working example:
// function to parse the http auth header
function http_digest_parse($txt)
{
// protect against missing data
$needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
$data = array();
preg_match_all('@(w+)=(?:(['"])([^$2]+)$2|([^s,]+))@', $txt, $matches, PREG_SET_ORDER);
foreach ($matches as $m) {
$data[$m[1]] = $m[3] ? trim($m[3],"",'") : trim($m[4],"",'");
unset($needed_parts[$m[1]]);
}
return $needed_parts ? false : $data;
}
Probably there's a more sophisticated way to trim the quotes within the regex, but I couldn't be bothered :-)
Greets, Lars
sergio dot carvalho at gmail dot com ¶
7 years ago
The only effective way I've found to wipe out the PHP_AUTH_DIGEST or PHP_AUTH_USER AND PHP_AUTH_PW credentials is to call the header HTTP/1.1 401 Unauthorized.
function clear_admin_access(){
header('HTTP/1.1 401 Unauthorized');
die('Admin access turned off');
}
ceo at l-i-e dot com ¶
12 years ago
To force a logout with Basic Auth, you can change the Realm out from under them to a different Realm.
This forces a new set of credentials for a new "Realm" on your server.
You just need to track the Realm name with the user/pass and change it around to something new/random as they log in and out.
I believe that this is the only 100% guaranteed way to get a logout in HTTP Basic Auth, and if it were part of the docs a whole lot of BAD user-contributed comments here could be deleted.
charly at towebs dot com ¶
17 years ago
A simpler approach on the post of:
bernard dot paques at bigfoot dot com
24-Sep-2004 01:42
This is another "patch" to the PHP_AUTH_USER and PHP_AUTH_PW server variables problem running PHP as a CGI.
First of all don't forget this fragment of code in your .htaccess (it's the only thing you need to make it work with mod_rewrite):
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization},L]
</IfModule>
Then login.php
<?php
$a = base64_decode( substr($_SERVER["REMOTE_USER"],6)) ;
if ( (strlen($a) == 0) || ( strcasecmp($a, ":" ) == 0 ))
{
header( 'WWW-Authenticate: Basic realm="Private"' );
header( 'HTTP/1.0 401 Unauthorized' );
}
else
{
list($name, $password) = explode(':', $a);
$_SERVER['PHP_AUTH_USER'] = $name;
$_SERVER['PHP_AUTH_PW'] = $password;
}
echo
'PHP_AUTH_USER =' . $_SERVER['PHP_AUTH_USER'] . '<br>';
echo 'PHP_AUTH_PW =' . $_SERVER['PHP_AUTH_PW'] . '<br>';
echo 'REMOTE_USER =' . $_SERVER['REMOTE_USER'] . '<br>';
?>
First, we decode the base64 encoded string discarding the first 6 characters of "Basic " and then we do a regular validation.
At the end of the script we print the variables to verify it's working. This should be ommited in the production version.
It's a variation of the script by Bernard Paques.
Thanks to him for that snippet.
emmanuel dot keller at net2000 dot ch ¶
20 years ago
Some servers won't support the HTTP1.0 specification and will give an error 500 (for instance). This happened with a server where I uploaded an authentication script.
If it happens, you can try the HTTP1.1 header syntax :
<?php
header("WWW-Authenticate: Basic realm="My Realm"");
header('status: 401 Unauthorized');
?>
h3ndrik ¶
11 years ago
On my configuration with php-cgi - after setting the RewriteRule - the correct variable would be: $_SERVER['REDIRECT_HTTP_AUTHORIZATION']
So the workaround for PhpCGI is:
Set in your .htaccess:
RewriteEngine on
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization},last]
Php workaround:
<?php
//set http auth headers for apache+php-cgi work around
if (isset($_SERVER['HTTP_AUTHORIZATION']) && preg_match('/Basics+(.*)$/i', $_SERVER['HTTP_AUTHORIZATION'], $matches)) {
list($name, $password) = explode(':', base64_decode($matches[1]));
$_SERVER['PHP_AUTH_USER'] = strip_tags($name);
$_SERVER['PHP_AUTH_PW'] = strip_tags($password);
}//set http auth headers for apache+php-cgi work around if variable gets renamed by apache
if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) && preg_match('/Basics+(.*)$/i', $_SERVER['REDIRECT_HTTP_AUTHORIZATION'], $matches)) {
list($name, $password) = explode(':', base64_decode($matches[1]));
$_SERVER['PHP_AUTH_USER'] = strip_tags($name);
$_SERVER['PHP_AUTH_PW'] = strip_tags($password);
}
?>
Ollie L ¶
12 years ago
I tried example 7, and at first I couldn't get it to work. It took me a while to spot that somewhere along the line, probably by the server, a seemingly random number was being added to the realm - so the valid_result variable wasn't calculated using the correct realm.
To get around this, or any similar problems, make the following changes to the example:
Around line 43 (44 if after next step ;) ):
$needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1, 'realm'=>1);
Before line 24:
$realm = $data['realm'];
These two steps get the real realm used for the authentication request, and substitute it into the "valid_response" query.
Hope this helps :)
djreficul at yahoo dot com ¶
17 years ago
Well, I think it's easy to make authentification works correctly. I use a session var to force authentication everytime a user visit the logging area.
<?php
if (!isset ($_SESSION['firstauthenticate'])) {
session_start();
}
function authenticate() {
header('WWW-Authenticate: Basic realm="Sistema autentificaci?n UnoAutoSur"');
header('HTTP/1_0 401 Unauthorized');
// header("Status: 401 Access Denied");
echo "Unauthorizedn";
exit;
}
if (!isset($_SERVER['PHP_AUTH_USER']) || strcmp ($_SERVER['PHP_AUTH_USER'],$user)!=0 ||
!isset ($_SERVER['PHP_AUTH_PW']) || strcmp($_SERVER['PHP_AUTH_PW'],$pass)!=0 || !isset ($_SESSION['firstauthenticate']) || !$_SESSION['firstauthenticate']) {
$_SESSION['firstauthenticate']=true;
authenticate();
} else {
//I destroy the session var now
session_unset();
//Your code below
}
?>
nuno at mail dot ideianet dot pt ¶
18 years ago
In Windows 2003 Server/IIS6 with the php4+ cgi I only get HTTP authentication working with:
<?php header("Status: 401 Access Denied"); ?>
with
<?php header('HTTP/1.0 401 Unauthorized'); ?>
doesn't work !
I also need in "Custom Errors" to select the range of "401;1" through "401;5" and click the "Set to Default" button.
Thanks rob at theblip dot com
snagnever at gmail dot com ¶
17 years ago
It forces a auth each time the page is accessed:
(maybe can save someone)
<?
header("Expires: Sat, 01 Jan 2000 00:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: post-check=0, pre-check=0",false);
header("Pragma: no-cache");
session_cache_limiter("public, no-store");
session_start();
function http_auth()
{
$_SESSION['AUTH'] = 1;
header('HTTP/1.0 401 Unauthorized');
header('WWW-Authenticate: Basic realm="sn4g auth system"');
// The actions to be done when the user clicks on 'cancel'
exit();
}
if( !isset($_SERVER['PHP_AUTH_USER']) or @$_SESSION['AUTH'] != 1 )
{
http_auth();
exit();
}
// Actions do be done when the user has logged
// rest, must clean the session array
$_SESSION = array();
session_destroy();
?>
jason ¶
18 years ago
on the php+mysql auth code by tigran at freenet dot am
There are some security weaknesses.
First
$user
and
$pass
are both insecure, they could leave this code open to SQL injection, you should always remove invalid characters in both, or at least encode them.
Actually storing passwords as MD5 hashes leaves you less work to secure.
Second security risks
The same mysql user has rights to both update and select, and possibly even insert and on your auth database no less.
Again the SQL inject attack may occur with this., and the end user could then change the users username, password, or anything else in relation to this.
Third items is more of a performance issue,
Do you really need to update the database, as updates are slower then selects, and if you do them every time they access the page, you are costing some speed penalty.
One option, if you want to use sql (I think mysql has it) is memory only databases, and create a table within memory, the stores a unique session identifier for each user, that is logged in, or alternatively if it's a single front end system, you could use db files.
kembl at example dot com ¶
16 years ago
# PHP (CGI mode) HTTP Authorization with ModRewrite:
# most right example with header check for non empty:
RewriteEngine on
RewriteCond %{HTTP:Authorization} !^$
RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization},
E=PHP_AUTH_USER:%{HTTP:Authorization},L]
najprogramato at post dot sk ¶
18 years ago
Don't use apache authentification in plain text. Is more better to use own script to generete new ID which is relevant to password. Apache auth data are sent to every page, so the posible mistake are known.
rob at theblip dot com ¶
19 years ago
Regarding HTTP authentication in IIS with the php cgi 4.3.4, there's one more step. I searched mightily and didn't find this information anywhere else, so here goes. When using HTTP auth with the php CGI, you need to do the following things:
1. In your php.ini file, set "cgi.rfc2616_headers = 0"
2. In Web Site Properties -> File/Directory Security -> Anonymous Access dialog box, check the "Anonymous access" checkbox and uncheck any other checkboxes (i.e. uncheck "Basic authentication," "Integrated Windows authentication," and "Digest" if it's enabled.) Click OK.
3. In "Custom Errors", select the range of "401;1" through "401;5" and click the "Set to Default" button.
It's this last step that is crucial, yet not documented anywhere. If you don't, instead of the headers asking for credentials, IIS will return its own fancy but useless 'you are not authenticated' page. But if you do, then the browser will properly ask for credentials, and supply them in the $_SERVER['PHP_AUTH_*'] elements.
marco dot moser at oltrefersina dot it ¶
17 years ago
I suggest to demand user's authentication and management to the web server (by .htaccess, ...):
1. configure a global /logon/ directory with a .htaccess file restricted access
2. use fopen wrapper:
$hh = @fopen("http://{$_SERVER['PHP_AUTH_USER']}:{$_SERVER['PHP_AUTH_PW']}".
@{$_SERVER['SERVER_NAME']}/logon/", "r");
if (!$hh) authenticate(); // usual header WWW-Authenticate ...
fclose($hh);
web at kwi dot dk ¶
16 years ago
While Digest authentication is still far superior to Basic authentication, there are a number of security issues that one must keep in mind.
In this respect, the Digest example given above is somewhat flawed, because the nonce never times out or otherwise become invalid. It thus becomes a password-equivalent (although to that specific URL only) and can be used by an eavesdropper to fetch the page at any time in the future, thus allowing the attacker to always access the latest version of the page, or (much worse) repeatedly invoke a CGI script -- for instance, if the user requests the URL "/filemanager?delete=somefile", the attacker can repeat this deletion at any point in the future, possibly after the file has been recreated.
And while it might not be possible to change GET data without reauthentication, cookies and POST data *can* be changed.
To protect against the first problem, the nonce can be made to include a timestamp, and a check added to ensure that nonces older than e.g. 30 minutes result in a new authentication request.
To solve the second problem, a one-time only nonce needs to be generated -- that is, all further requests using a particular nonce must be refused.
One way to do this: When the user requests an action such as "deletefile", store a randomly generated nonce in a session variable, issue a 401 authentication challenge with that nonce, and then check against the stored value when receiving the authentication (and clear the session variable).
This way, although a possible eavesdropper receives the nonce and thus gains the ability to perform the action, he can only perform it once -- and the user was going to perform it anyway. (Only the user or the attacker, but not both, gets to perform the action, so it's safe.)
Of course, at some point, the security can only be improved by switching to HTTPS / SSL / TLS (this is for instance the only way to defend against man-in-the-middle attacks). You decide the level of security.
idbobby at rambler dot ru ¶
12 years ago
First of all, sorry for my English.
One more authorization script with logout solution.
In script given by meint_at_meint_dot_net (http://www.php.net/manual/en/features.http-auth.php#93859) rewrite_module is used. If there are any problems with that module and possibilities of administration of the web-server are restricted (including restrictions for use of .htaccess) then you can use this solution.
index.php
---------
<?php
$auth_realm
= 'My realm';
require_once
'auth.php';
echo
"You've logged in as {$_SESSION['username']}<br>";
echo '<p><a href="?action=logOut">LogOut</a></p>'?>
auth.php
--------
<?php
$_user_
= 'test';
$_password_ = 'test';session_start();$url_action = (empty($_REQUEST['action'])) ? 'logIn' : $_REQUEST['action'];
$auth_realm = (isset($auth_realm)) ? $auth_realm : '';
if (isset(
$url_action)) {
if (is_callable($url_action)) {
call_user_func($url_action);
} else {
echo 'Function does not exist, request terminated';
};
};
function
logIn() {
global $auth_realm;
if (!isset(
$_SESSION['username'])) {
if (!isset($_SESSION['login'])) {
$_SESSION['login'] = TRUE;
header('WWW-Authenticate: Basic realm="'.$auth_realm.'"');
header('HTTP/1.0 401 Unauthorized');
echo 'You must enter a valid login and password';
echo '<p><a href="?action=logOut">Try again</a></p>';
exit;
} else {
$user = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : '';
$password = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : '';
$result = authenticate($user, $password);
if ($result == 0) {
$_SESSION['username'] = $user;
} else {
session_unset($_SESSION['login']);
errMes($result);
echo '<p><a href="">Try again</a></p>';
exit;
};
};
};
}
function
authenticate($user, $password) {
global $_user_;
global $_password_;
if ((
$user == $_user_)&&($password == $_password_)) { return 0; }
else { return 1; };
}
function
errMes($errno) {
switch ($errno) {
case 0:
break;
case 1:
echo 'The username or password you entered is incorrect';
break;
default:
echo 'Unknown error';
};
}
function
logOut() {session_destroy();
if (isset($_SESSION['username'])) {
session_unset($_SESSION['username']);
echo "You've successfully logged out<br>";
echo '<p><a href="?action=logIn">LogIn</a></p>';
} else {
header("Location: ?action=logIn", TRUE, 301);
};
if (isset($_SESSION['login'])) { session_unset($_SESSION['login']); };
exit;
}?>
s dot i dot g at gmx dot com ¶
13 years ago
<?php// try to mimic cpanel logout style
// only diff is usr & pwd field is cleared when re-login
// tested with ff2 & ie8session_start();$username = "test";
$password = "test";
if(isset(
$_GET['logout']))
{
unset($_SESSION["login"]);
echo "You have logout ... ";
echo "[<a href='" . $_SERVER['PHP_SELF'] . "'>Login</a>]";
exit;
}
if (!isset(
$_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW']) || !isset($_SESSION["login"]))
{
header("WWW-Authenticate: Basic realm="Test"");
header("HTTP/1.0 401 Unauthorized");
$_SESSION["login"] = true;
echo "You are unauthorized ... ";
echo "[<a href='" . $_SERVER['PHP_SELF'] . "'>Login</a>]";
exit;
}
else
{
if($_SERVER['PHP_AUTH_USER'] == $username && $_SERVER['PHP_AUTH_PW'] == $password)
{
echo "You have logged in ... ";
echo "[<a href='" . $_SERVER['PHP_SELF'] . "?logout'>Logout</a>]";
}
else
{
unset($_SESSION["login"]);
header("Location: " . $_SERVER['PHP_SELF']);
}
}// content here?>
siberion at hotmail dot com ¶
17 years ago
I came up with another approach to work around the problem of browsers caching WWW authentication credentials and creating logout problems. While most browsers have some kind of way to wipe this information, I prefer having my website to take care of the task instead of relying on the user's sanity.
Even with Lalit's method of creating a random realm name, it was still possible to get back into the protected area using the back button in Firefox, so that didn't work. Here's my solution:
Since browsers attach the credentials to specific URLs, use virtual paths where a component of the path is actually a PHP script, and everything following it is part of the URI, such as:
http://www.example.com/some_dir/login.php/auth/8f631b92/
By choosing a different number for the last component of the URL, browsers can be tricked into thinking that they are dealing with a completely different website, and thus prompting the user for credentials again.
Note that using a random, unrestricted number will still allow the user to hit the back button to get back into the page. You should keep track of this number in a server-side file or database and regenerate it upon each successful login, so that the last number(s) become invalid. Using an invalid number might result in a 403 response or, depending on how you feel that day, a 302 to a nasty website.
Care should be taken when linking from the page generated in this case, since relative links will be relative to the virtual and non-existant directory rather than the true script directory.
Hope this helps somebody.
Paul ¶
19 years ago
Here is a extremely easy way to successfully logout.
<?php
if ( $realm == '' )
$realm = mt_rand( 1, 1000000000 );
header( 'WWW-Authenticate: Basic realm='.$realm );
?>
To log the user out simply change the value of $realm
steuber at aego dot de ¶
18 years ago
Quite a good solution for the logout problem:
Just tell browser that it is successfully logged in!
This works as follows:
1. User clicks logout button
2. Script sends 401 Header
3. User does NOT enter a password
4. If no password is entered, script sends 200 Header
So the browser remembers no password as a valid password.
Example:
<?php
if (
(!isset($_SERVER['PHP_AUTH_USER']))
||(
($_GET["login"]=="login")
&& !(
($_SERVER['PHP_AUTH_USER']=="validuser")
&& ($_SERVER['PHP_AUTH_PW']=="validpass")
)
)
||(
($_GET["logout"]=="logout")
&& !($_SERVER['PHP_AUTH_PW']=="")
)
) {
Header("WWW-Authenticate: Basic realm="Realm"");
Header("HTTP/1.0 401 Unauthorized");
echo "Not logged out...<br>n";
echo "<a href="index.php?login=login">Login</a>";
exit;
} else if ($_SERVER['PHP_AUTH_PW']=="") {
echo "Logged out...<br>n";
echo "<a href="index.php?login=login">Login</a>";
exit;
}
?>
Whatabrain ¶
16 years ago
Back to the problem of authenticating in CGI mode... mcbethh suggested using this to set a local variable in php:
RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization},L]
It didn't work. I couldn't see the variable. My solution is pretty round-about, but it works:
RewriteEngine on
RewriteCond %{HTTP:Authorization} !^$
RewriteCond %{REQUEST_METHOD} =GET
RewriteCond %{QUERY_STRING} =""
RewriteRule ^page.php$ page.php?login=%{HTTP:Authorization}$1
This causes the Auth string to be added to the URL if there are no parameters and it's a GET request. This prevents POSTs and parameter lists from being corrupted.
Then, in the PHP script, I store the Auth string as a session cookie.
So the only way to log in to my script is to go to the url with no parameters.
Доброго времени суток друзья! Давай с Вами рассмотрим регистрацию пользователей на PHP. Для начала давайте определим условия для нашей регистрации пользователей:
Условия для регистрации пользователей
- Пароль шифруем при помощи алгоритма MD5
- Пароль будем «солить»
- Проверка на занятость Логина
- Активация пользователя письмом.
- Запись и хранение данных в СУБД MySQL
Для написание данного скрипта нам нужно понять, что такое регистрация пользователя. Регистрация пользователя – это получения данных реального пользователя, обработка и хранение данных.
Если объяснять простыми словами то регистрация это всего лишь запись и хранение определенных данных по которым мы можем авторизировать пользователя в нашем случае – это Логин и Пароль.
Авторизация — предоставление определённому лицу или группе лиц прав на выполнение определённых действий, а также процесс проверки данных прав при попытке выполнения этих действий. Проше говоря с помощью авторизации мы можем разграничить доступ к тому или иному контенту на нашем сайте.
Рассмотрим структуру каталогов скриптов для реализации нашей регистрации с авторизацией. Нам нужно разбить скрипты на логические составляющие. Модули регистрации и авторизации мы поместив в отдельный каталог. Так же в отдельные каталоги мы поместим подключение к базе данных MySQL, файл с пользовательскими функциями, файл стилей CSS и наш шаблон HTML. Данная структура позволяет быстро ориентироваться в скриптах. Представьте себе, что у Вас большой сайт с кучей модулями и т.д. и если не будет порядка, то будет очень сложно что-то отыскать в таком бардаке.
Так как мы будем хранить все данные в СУБД MySQL, то давайте создадим не большую таблицу в которой будем хранить данные о регистрации.
Для начала нужно создать таблицу в базе данных. Таблицу назовем bez_reg где bez – это префикс таблицы, а reg название таблицы.
Структура таблицы: bez_reg
--
-- Структура таблицы `bez_reg`
--
CREATE TABLE IF NOT EXISTS `bez_reg` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`login` varchar(200) NOT NULL,
`pass` varchar(32) NOT NULL,
`salt` varchar(32) NOT NULL,
`active_hex` varchar(32) NOT NULL,
`status` int(1) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Теперь создадим основные скрипты для дальнейшей работы.
Файл INDEX.PHP
<?php
/**
* Главный файл (переключатель)
* Site: https://bezramok-tlt.ru
* Регистрация пользователя письмом
*/
//Запускаем сессию
session_start();
//Устанавливаем кодировку и вывод всех ошибок
header('Content-Type: text/html; charset=UTF8');
error_reporting(E_ALL);
//Включаем буферизацию содержимого
ob_start();
//Определяем переменную для переключателя
$mode = isset($_GET['mode']) ? $_GET['mode'] : false;
$user = isset($_SESSION['user']) ? $_SESSION['user'] : false;
$err = array();
//Устанавливаем ключ защиты
define('BEZ_KEY', true);
//Подключаем конфигурационный файл
include './config.php';
//Подключаем скрипт с функциями
include './func/funct.php';
//подключаем MySQL
include './bd/bd.php';
switch($mode)
{
//Подключаем обработчик с формой регистрации
case 'reg':
include './scripts/reg/reg.php';
include './scripts/reg/reg_form.html';
break;
//Подключаем обработчик с формой авторизации
case 'auth':
include './scripts/auth/auth.php';
include './scripts/auth/auth_form.html';
include './scripts/auth/show.php';
break;
}
//Получаем данные с буфера
$content = ob_get_contents();
ob_end_clean();
//Подключаем наш шаблон
include './html/index.html';
?>
Файл CONFIG.PHP
<?php
/**
* Конфигурационный файл
* Site: https://bezramok-tlt.ru
* Регистрация пользователя письмом
*/
//Ключ защиты
if(!defined('BEZ_KEY'))
{
header("HTTP/1.1 404 Not Found");
exit(file_get_contents('./404.html'));
}
//Адрес базы данных
define('BEZ_DBSERVER','localhost');
//Логин БД
define('BEZ_DBUSER','');
//Пароль БД
define('BEZ_DBPASSWORD','');
//БД
define('BEZ_DATABASE','');
//Префикс БД
define('BEZ_DBPREFIX','bez_');
//Errors
define('BEZ_ERROR_CONNECT','Немогу соеденится с БД');
//Errors
define('BEZ_NO_DB_SELECT','Данная БД отсутствует на сервере');
//Адрес хоста сайта
define('BEZ_HOST','http://'. $_SERVER['HTTP_HOST'] .'/');
//Адрес почты от кого отправляем
define('BEZ_MAIL_AUTOR','Регистрация на http://bezramok-tlt.ru <no-reply@bezramok-tlt.ru>');
?>
Файл 404.HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf8" />
<title>Ошибка 404</title>
</head>
<body>
<table width="700" cellpadding="4" cellspacing="1" border="0" align="center">
<tr>
<td>
<h1>Ошибка 404</h1>
</td>
</tr>
<tr>
<td>
<h2>
На странице произошла ошибка 404
</h2>
</td>
</tr>
<tr>
<td>
<span class="leftMenu"><a href="javascript:history.back(-1)">Вернуться</a></span>
</td>
</tr>
</table>
</body>
</html>
Файл BD.PHP
<?php
/**
* Подключение к базе данных
* Site: https://bezramok-tlt.ru
* Регистрация пользователя письмом
*/
//Ключ защиты
if(!defined('BEZ_KEY'))
{
header("HTTP/1.1 404 Not Found");
exit(file_get_contents('./../404.html'));
}
//Соединение с БД MySQL
$db_connect = mysql_connect( BEZ_DBSERVER, BEZ_DBUSER, BEZ_DBPASSWORD ) or die(BEZ_ERROR_CONNECT);
define('BEZ_CONNECT', $db_connect);
mysql_select_db( BEZ_DATABASE, BEZ_CONNECT )or die(BEZ_NO_DB_SELECT);
//Устанавливаем кодировку UTF8
mysql_query ("SET NAMES utf8");
mysql_query ("set character_set_client='utf8'");
mysql_query ("set character_set_results='utf8'");
mysql_query ("set collation_connection='utf8_general_ci'");
?>
Файл INDEX.HTML
<!DOCTYPE html>
<html>
<head>
<!-- Start META -->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="keywords" content="Регистрация пользователей PHP MySQL, Авторизация пользователей PHP MySQL" />
<meta name="description" content="Регистрация пользователей PHP MySQL с активацией письмом" />
<!-- TITLE -->
<title>Регистрация пользователей PHP MySQL с активацией письмом</title>
<!-- Start Sheets CSS -->
<link href="./css/style.css" rel="stylesheet" type="text/css">
</head>
<body>
<div id="wrap">
<div id="menu">
<div class="menu">
<ul>
<li><a href="<?php echo BEZ_HOST; ?>less/reg/?mode=auth">Войти</a></li>
<li><a href="<?php echo BEZ_HOST; ?>less/reg/?mode=reg">Регистрация</a></li>
</ul>
</div>
</div>
<div style="clear:both;"></div>
<div id="content">
<?php echo $content; ?>
</div>
</div>
</body>
</html>
Файл FUNCT.PHP
<?php
/**
* Файл с пользовательскими функциями
* Site: http://bezramok-tlt.ru
* Регистрация пользователя письмом
*/
//Ключ защиты
if(!defined('BEZ_KEY'))
{
header("HTTP/1.1 404 Not Found");
exit(file_get_contents('./../404.html'));
}
/**Функция экранирования вносимых данных
*@param array $data
*/
function escape_str($data)
{
if(is_array($data))
{
if(get_magic_quotes_gpc())
$strip_data = array_map("stripslashes", $data);
$result = array_map("mysql_real_escape_string", $strip_data);
return $result;
}
else
{
if(get_magic_quotes_gpc())
$data = stripslashes($data);
$result = mysql_real_escape_string($data);
return $result;
}
}
/**Отпровляем сообщение на почту
* @param string $to
* @param string $from
* @param string $title
* @param string $message
*/
function sendMessageMail($to, $from, $title, $message)
{
//Адресат с отправителем
//$to = $to;
//$from = $from;
//Формируем заголовок письма
$subject = $title;
$subject = '=?utf-8?b?'. base64_encode($subject) .'?=';
//Формируем заголовки для почтового сервера
$headers = "Content-type: text/html; charset="utf-8"rn";
$headers .= "From: ". $from ."rn";
$headers .= "MIME-Version: 1.0rn";
$headers .= "Date: ". date('D, d M Y h:i:s O') ."rn";
//Отправляем данные на ящик админа сайта
if(!mail($to, $subject, $message, $headers))
return 'Ошибка отправки письма!';
else
return true;
}
/**функция вывода ошибок
* @param array $data
*/
function showErrorMessage($data)
{
$err = '<ul>'."n";
if(is_array($data))
{
foreach($data as $val)
$err .= '<li style="color:red;">'. $val .'</li>'."n";
}
else
$err .= '<li style="color:red;">'. $data .'</li>'."n";
$err .= '</ul>'."n";
return $err;
}
/**Простая обертка для запросов к MySQL
* @param string $sql
*/
function mysqlQuery($sql)
{
$res = mysql_query($sql);
/* Проверяем результат
Это показывает реальный запрос, посланный к MySQL, а также ошибку. Удобно при отладке.*/
if(!$res)
{
$message = 'Неверный запрос: ' . mysql_error() . "n";
$message .= 'Запрос целиком: ' . $sql;
die($message);
}
return $res;
}
/**Простой генератор соли
* @param string $sql
*/
function salt()
{
$salt = substr(md5(uniqid()), -8);
return $salt;
}
Давайте приступим к написанию регистрации. Для начала нам нужно будет сделать шаблон формы регистрации,
чтобы пользователь смог внести свои данные для обработки. Далее нам нужно будет написать сам обработчик формы,
который проверит на корректность введенные данные пользователя. После того как данные успешно проверенны записываем
их в нашу базу данных и отправляем письмо пользователю для активации его аккаунта.
Файл REG.PHP
<?php
/**
* Обработчик формы регистрации
* Site: http://bezramok-tlt.ru
* Регистрация пользователя письмом
*/
//Ключ защиты
if(!defined('BEZ_KEY'))
{
header("HTTP/1.1 404 Not Found");
exit(file_get_contents('./../../404.html'));
}
//Выводим сообщение об удачной регистрации
if(isset($_GET['status']) and $_GET['status'] == 'ok')
echo '<b>Вы успешно зарегистрировались! Пожалуйста активируйте свой аккаунт!</b>';
//Выводим сообщение об удачной регистрации
if(isset($_GET['active']) and $_GET['active'] == 'ok')
echo '<b>Ваш аккаунт на http://bezramok-tlt.ru успешно активирован!</b>';
//Производим активацию аккаунта
if(isset($_GET['key']))
{
//Проверяем ключ
$sql = 'SELECT *
FROM `'. BEZ_DBPREFIX .'reg`
WHERE `active_hex` = "'. escape_str($_GET['key']) .'"';
$res = mysqlQuery($sql);
if(mysql_num_rows($res) == 0)
$err[] = 'Ключ активации не верен!';
//Проверяем наличие ошибок и выводим пользователю
if(count($err) > 0)
echo showErrorMessage($err);
else
{
//Получаем адрес пользователя
$row = mysql_fetch_assoc($res);
$email = $row['login'];
//Активируем аккаунт пользователя
$sql = 'UPDATE `'. BEZ_DBPREFIX .'reg`
SET `status` = 1
WHERE `login` = "'. $email .'"';
$res = mysqlQuery($sql);
//Отправляем письмо для активации
$title = 'Ваш аккаунт на http://bezramok-tlt.ru успешно активирован';
$message = 'Поздравляю Вас, Ваш аккаунт на http://bezramok-tlt.ru успешно активирован';
sendMessageMail($email, BEZ_MAIL_AUTOR, $title, $message);
/*Перенаправляем пользователя на
нужную нам страницу*/
header('Location:'. BEZ_HOST .'less/reg/?mode=reg&active=ok');
exit;
}
}
/*Если нажата кнопка на регистрацию,
начинаем проверку*/
if(isset($_POST['submit']))
{
//Утюжим пришедшие данные
if(empty($_POST['email']))
$err[] = 'Поле Email не может быть пустым!';
else
{
if(!preg_match("/^[a-z0-9_.-]+@([a-z0-9]+.)+[a-z]{2,6}$/i", $_POST['email']))
$err[] = 'Не правильно введен E-mail'."n";
}
if(empty($_POST['pass']))
$err[] = 'Поле Пароль не может быть пустым';
if(empty($_POST['pass2']))
$err[] = 'Поле Подтверждения пароля не может быть пустым';
//Проверяем наличие ошибок и выводим пользователю
if(count($err) > 0)
echo showErrorMessage($err);
else
{
/*Продолжаем проверять введеные данные
Проверяем на совподение пароли*/
if($_POST['pass'] != $_POST['pass2'])
$err[] = 'Пароли не совподают';
//Проверяем наличие ошибок и выводим пользователю
if(count($err) > 0)
echo showErrorMessage($err);
else
{
/*Проверяем существует ли у нас
такой пользователь в БД*/
$sql = 'SELECT `login`
FROM `'. BEZ_DBPREFIX .'reg`
WHERE `login` = "'. escape_str($_POST['email']) .'"';
$res = mysqlQuery($sql);
if(mysql_num_rows($res) > 0)
$err[] = 'К сожалению Логин: <b>'. $_POST['email'] .'</b> занят!';
//Проверяем наличие ошибок и выводим пользователю
if(count($err) > 0)
echo showErrorMessage($err);
else
{
//Получаем ХЕШ соли
$salt = salt();
//Солим пароль
$pass = md5(md5($_POST['pass']).$salt);
/*Если все хорошо, пишем данные в базу*/
$sql = 'INSERT INTO `'. BEZ_DBPREFIX .'reg`
VALUES(
"",
"'. escape_str($_POST['email']) .'",
"'. $pass .'",
"'. $salt .'",
"'. md5($salt) .'",
0
)';
$res = mysqlQuery($sql);
//Отправляем письмо для активации
$url = BEZ_HOST .'less/reg/?mode=reg&key='. md5($salt);
$title = 'Регистрация на http://bezramok-tlt.ru';
$message = 'Для активации Вашего акаунта пройдите по ссылке
<a href="'. $url .'">'. $url .'</a>';
sendMessageMail($_POST['email'], BEZ_MAIL_AUTOR, $title, $message);
//Сбрасываем параметры
header('Location:'. BEZ_HOST .'less/reg/?mode=reg&status=ok');
exit;
}
}
}
}
?>
Файл REG_FORM.HTML
<h2>Регистрация пользователей PHP MySQL с активацией письмом</h2>
<form action="" method="POST">
<table>
<tr>
<td>E-mail<font color="red">*</font>:</td>
<td><input type="text" size="30" name="email"></td>
</tr>
<tr>
<td>Пароль<font color="red">*</font>:</td>
<td><input type="password" size="30" maxlength="20" name="pass"></td>
</tr>
<tr>
<td>Подтверждения пароля<font color="red">*</font>:</td>
<td><input type="password" size="30" maxlength="20" name="pass2"></td>
</tr>
<tr>
<td> </td>
<td colspan="2"><input type="submit" value="Зарегистроваться" name="submit"></td>
</tr>
</table>
</form>
<br>Поля со значком <font color="red">*</font> обязательны для заполнения
Так как регистрация пользователей у нас готова, самое время написать авторизацию. Создадим форму для авторизации
пользователей, далее напишем обработчик формы авторизации и на последок сделаем скрипт show.php который
будет показывать нам авторизированны мы в системе или нет.
Файл AUTH.PHP
<?php
/**
* Обработчик формы авторизации
* Site: http://bezramok-tlt.ru
* Авторизация пользователя
*/
//Ключ защиты
if(!defined('BEZ_KEY'))
{
header("HTTP/1.1 404 Not Found");
exit(file_get_contents('./../../404.html'));
}
//Если нажата кнопка то обрабатываем данные
if(isset($_POST['submit']))
{
if(empty($_POST['email']))
$err[] = 'Не введен Логин';
if(empty($_POST['pass']))
$err[] = 'Не введен Пароль';
//Проверяем наличие ошибок и выводим пользователю
if(count($err) > 0)
echo showErrorMessage($err);
else
{
/*Создаем запрос на выборку из базы
данных для проверки подлиности пользователя*/
$sql = 'SELECT *
FROM `'. BEZ_DBPREFIX .'reg`
WHERE `login` = "'. escape_str($_POST['email']) .'"
AND `status` = 1';
$res = mysqlQuery($sql);
//Если логин совподает, проверяем пароль
if(mysql_num_rows($res) > 0)
{
//Получаем данные из таблицы
$row = mysql_fetch_assoc($res);
if(md5(md5($_POST['pass']).$row['salt']) == $row['pass'])
{
$_SESSION['user'] = true;
//Сбрасываем параметры
header('Location:'. BEZ_HOST .'less/reg/?mode=auth');
exit;
}
else
echo showErrorMessage('Неверный пароль!');
}
else
echo showErrorMessage('Логин <b>'. $_POST['email'] .'</b> не найден!');
}
}
?>
Файл AUTH_FORM.HTML
<h2>Введите свой Логин и Пароль для входа!</h2>
<form action="" method="POST">
<table>
<tr>
<td>E-mail:</td>
<td><input type="text" size="30" name="email"></td>
</tr>
<tr>
<td>Пароль:</td>
<td><input type="password" size="30" maxlength="20" name="pass"></td>
</tr>
<tr>
<td> </td>
<td colspan="2"><input type="submit" value="Войти" name="submit"></td>
</tr>
</table>
</form>
Файл SHOW.PHP
<?php
/**
* Скрипт распределения ресурсов
* Site: http://bezramok-tlt.ru
* Проверяем права на чтение данных,
* только для зарегистрированных пользователей
*/
//Ключ защиты
if(!defined('BEZ_KEY'))
{
header("HTTP/1.1 404 Not Found");
exit(file_get_contents('./../../404.html'));
}
//Проверяем зашел ли пользователь
if($user === false)
echo '<h3>Доступ закрыт, Вы не вошли в систему!</h3>'."n";
if($user === true)
echo '<h3>Поздравляю, Вы вошли в систему!</h3>'."n";
?>
Автор не несет ответственности за использования данных скриптов у себя на сайте. Вы можете их использовать на свой страх и риск!
Для тех у кого последняя версия PHP выкладываю данный скрипт с использованием PDO т.к. расширение MySQL устарело и было удалено из новой версии PHP. Скачать регистрация и авторизация php mysql pdo
Архив обновлен 24.02.2015г.
Внимание: Если вы используете данный скрипт на локальном сервере типа DENWER, XAMPP, то не
стоит ждать писем на свой почтовый ящик. Письма лежат в заглушке sendmail. В Denwer вы их можете
найти по пути Z:tmp!sendmail открыть данные файлы вы сможете в любом почтовом клиенте.
Скачать: Регистрация и Авторизация на PHP + MySQL