Будем учиться делать простую аутентификацию пользователей на сайте. На сайте могут быть страницы только для авторизованных пользователей и они будут полноценно функционировать, если добавить к ним наш блок аутентификации. Чтобы его создать, нужна база данных MySQL. Она может иметь 5 колонок (минимум), а может и больше, если вы хотите добавить информацию о пользователях. Назовём базу данных “Userauth”.

Создадим в ней следующие поля: ID для подсчёта числа пользователей, UID для уникального идентификационного номера пользователя, Username для имени пользователя, Email для адреса его электронной почты и Password для пароля. Вы можете использовать для авторизации пользователя и уже имеющуюся у Вас базу данных, только, как и в случае с новой базой данных, создайте в ней следующую таблицу.

Код MySQL

CREATE TABLE `users` (`ID` int (11) NOT NULL AUTO_INCREMENT, `UID` int (11) NOT NULL, `Username` text NOT NULL, `Email` text NOT NULL, `Password` text NOT NULL, PRIMARY KEY (`ID`)) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

Теперь создадим файл "sql.php". Он отвечает за подключение к базе данных. Данный код, во первых, создаёт переменные для сервера и пользователя, когда он подключается к серверу. Во-вторых, он выберет базу данных, в данном случае "USERAUTH". Этот файл нужно подключить в "log.php" и "reg.php" для доступа к базе данных.

Код PHP

//Ваше имя пользователя MySQL $pass = "redere"; //пароль $conn = mysql_connect ($server, $user, $pass);//соединение с сервером $db = mysql_select_db ("userauth", $conn);//выбор базы данных if (!$db) { //если не может выбрать базу данных echo "Извините, ошибка:(/>";//Показывает сообщение об ошибке exit (); //Позволяет работать остальным скриптам PHP } ?>

Далее страница входа, пусть она называется "login.php". Во-первых, она проверяет введённые данные на наличие ошибок. Страница имеет поля для имени пользователя, пароля, кнопку отправки и ссылку для регистрации. Когда пользователь нажмёт кнопку «Вход», форма будет обработана кодом из файла "log.php", а затем произойдёт вход в систему.

Код PHP

0) { //если есть ошибки сессии $err = "

"; //Start a table foreach ($_SESSION["ERRMSG"] as $msg) {//распознавание каждой ошибки $err .= ""; //запись её в переменную } $err .= "
" . $msg . "
"; //закрытие таблицы unset ($_SESSION["ERRMSG"]); //удаление сессии } ?> Форма входа
Имя пользователя
Пароль
Регистрация

Затем пишем скрипт для входа в систему. Назовём его "log.php". Он имеет функцию для очистки входных данных от SQL-инъекций, которые могут испортить ваш скрипт. Во-вторых, он получает данные формы и проверяет их на правильность. Если входные данные правильны, скрипт отправляет пользователя на страницу авторизованных пользователей, если нет – устанавливает ошибки и отправляет пользователя на страницу входа.

Код PHP

//начало сессии для записи function Fix($str) { //очистка полей $str = trim($str); if (get_magic_quotes_gpc()) { $str = stripslashes ($str); } //массив для сохранения ошибок $errflag = false ; //флаг ошибки $username = Fix($_POST["username"]);//имя пользователя $password = Fix($_POST["password"]);//пароль } //проверка пароля if ($password == "") { $errmsg = "Password missing"; //ошибка $errflag = true ; //поднимает флаг в случае ошибки } //если флаг ошибки поднят, направляет обратно к форме регистрации //записывает ошибки session_write_close(); //закрытие сессии //перенаправление exit (); } //запрос к базе данных $qry = "SELECT * FROM `users` WHERE `Username` = "$username" AND `Password` = "" . md5 ($password) . """; $result = mysql_query ($qry); //проверка, был ли запрос успешным (есть ли данные по нему) if (mysql_num_rows ($result) == 1) { while ($row = mysql_fetch_assoc ($result)) { $_SESSION["UID"] = $row["UID"];//получение UID из базы данных и помещение его в сессию $_SESSION["USERNAME"] = $username;//устанавливает, совпадает ли имя пользователя с сессионным session_write_close(); //закрытие сессии header("location: member.php");//перенаправление } } else { $_SESSION["ERRMSG"] = "Invalid username or password"; //ошибка session_write_close(); //закрытие сессии header("location: login.php"); //перенаправление exit (); } ?>

Сделаем страницу регистрации, назовём её "register.php". Она похожа на страницу входа, только имеет на несколько полей больше, а вместо ссылки на регистрацию – ссылку на login.php на случай, если у пользователя уже есть аккаунт.

Код PHP

0) { //если есть ошибки сессии $err = "

"; //начало таблицы foreach ($_SESSION["ERRMSG"] as $msg) {//устанавливает каждую ошибку $err .= ""; //записывает их в переменную } $err .= "
" . $msg . "
"; //конец таблицы unset ($_SESSION["ERRMSG"]); //уничтожает сессию } ?> Форма регистрации
Имя пользователя
E-mail
Пароль
Повтор пароля
У меня есть аккаунт

Теперь сделаем скрипт регистрации в файле "reg.php". В него будет включён "sql.php" для подключения к к базе данных. Используется и та же функция, что и в скрипте входа для очистки поля ввода. Устанавливаются переменные для возможных ошибок. Далее – функция для создания уникального идентификатора, который никогда ранее не предоставлялся. Затем извлекаются данные из формы регистрации и проверяются. Происходит проверка, что адрес электронной почты указан в нужном формате, а также, правильно ли повторно указан пароль. Затем скрипт проверяет, нет ли в базе данных пользователя с таким же именем, и, если есть, сообщает об ошибке. И, наконец, код добавляет пользователя в базу данных.

Код PHP

//начало сессии для записи function Fix($str) { //очистка полей $str = @trim($str); if (get_magic_quotes_gpc()) { $str = stripslashes ($str); } return mysql_real_escape_string ($str); } $errmsg = array (); //массив для хранения ошибок $errflag = false ; //флаг ошибки $UID = "12323543534523453451465685454";//уникальный ID $username = Fix($_POST["username"]);//имя пользователя $email = $_POST["email"]; //Email $password = Fix($_POST["password"]);//пароль $rpassword = Fix($_POST["rpassword"]);//повтор пароля //проверка имени пользователя if ($username == "") { $errmsg = "Username missing"; //ошибка $errflag = true ; //поднимает флаг в случае ошибки } //проверка Email if(!eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@+(\.+)*(\.{2,3})$", $email)) { //должен соответствовать формату: [email protected] $errmsg = "Invalid Email"; //ошибка $errflag = true ; //поднимает флаг в случае ошибки } //проверка пароля if ($password == "") { $errmsg = "Password missing"; //ошибка $errflag = true ; //поднимает флаг в случае ошибки } //проверка повтора пароля if ($rpassword == "") { $errmsg = "Repeated password missing";//ошибка $errflag = true ; //поднимает флаг в случае ошибки } //проверка валидности пароля if (strcmp($password, $rpassword) != 0) { $errmsg = "Passwords do not match";//ошибка $errflag = true ; //поднимает флаг в случае ошибки } //проверка, свободно ли имя пользователя if ($username != "") { $qry = "SELECT * FROM `users` WHERE `Username` = "$username""; //запрос к MySQL $result = mysql_query ($qry); if ($result) { if (mysql_num_rows ($result) > 0) {//если имя уже используется $errmsg = "Username already in use"; //сообщение об ошибке $errflag = true; //поднимает флаг в случае ошибки } mysql_free_result ($result); } } //если данные не прошли валидацию, направляет обратно к форме регистрации if ($errflag) { $_SESSION["ERRMSG"] = $errmsg; //сообщение об ошибке session_write_close(); //закрытие сессии header("location: register.php");//перенаправление exit (); } //добавление данных в базу $qry = "INSERT INTO `userauth`.`users`(`UID`, `Username`, `Email`, `Password`) VALUES("$UID","$username","$email","" . md5 ($password) . "")"; $result = mysql_query ($qry); //проверка, был ли успешным запрос на добавление if ($result) { echo "Благодарим Вас за регистрацию, " .$username . ". Пожалуйста, входите сюда"; exit (); } else { die ("Ошибка, обратитесь позже"); } ?>

Ещё нужно сделать скрипт для выхода пользователя из системы. Он прекращает сессию для пользователя с данным уникальным идентификатором и именем, а затем перенаправляет пользователя на страницу входа в систему.

Код PHP

И, наконец, скрипт "auth.php" можно использовать, чтобы сделать страницы доступными только для авторизованных пользователей. Он проверяет данные входа и, если они верны, позволяет пользователю просматривать страницы, а если нет, просит авторизоваться. Кроме того, если кто-то попытается взломать сайт создав одну из сессий, она будет прервана, как в общем случае.

Код PHP

Одно из условий в коде выше является предметом вопроса в .

Следующий код нужно вставить на страницу для авторизованных пользователей, она называется, например, "member.php", а у Вас может называться как угодно.

Код PHP

Вам разрешён доступ к этой странице. Выйти ( )

Аутентификация пользователей готова!

Буквально вчера я решил приступить к разработке личного кабинете одного безымянного сайта. Передо мной встал вопрос по поводу внешнего вида формы авторизации, мне, откровенно, не хотелось заниматься дизайном формы, делать всплывающие подсказки, да и в целом уделять огромное внимание форме. Я сдуру ринулся искать готовые решения, увидел достаточно безвкусных форм. Думал подыскать какой-нибудь готовый компонент, готовое расширение, но в большинстве своём они разочаровали меня. Блуждая по форумам, мне показалось интересным разыграть карту с HTTP Authentication: Basic. Я отправился читать мануал, прежде был недостаточно осведомлён об данном способе. Далее и начались проблемы.

Деваться было некуда, пошастал по сети в поисках сайтов, что возьмутся генерировать формы, код, стили. Тщетны оказались мои попытки облегчить себе задачу. Выход невелик, я приступил к разрешению проблемы. Одно время я старался сварганить решение с помощью.htaccess, нашел такое.

RewriteCond %{HTTP:Authorization} ^Basic.* RewriteRule (.*) index.php?authorization=%{HTTP:Authorization}

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

Hello {$_SERVER["PHP_AUTH_USER"]}.

"; echo "

Вы ввели пароль {$_SERVER["PHP_AUTH_PW"]}.

"; } ?>

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

get("user") === null) { $db = JFactory::getDbo(); $query = $db->getQuery(true); $query->select("*"); $query->from("#__beda_users"); $query->where("codeword = ".$query->quote($_SERVER["PHP_AUTH_PW"])); if($res = $db->setQuery($query)->loadAssoc()) { $session->set("user", $res); } else { header("WWW-Authenticate: Basic realm="My Realm""); header("HTTP/1.0 401 Unauthorized"); } } else { //Нам бы сюда } } ?>

Работает, значения меняются, сессия создаётся. Замечательно, но в случае с кликом на отмену, значения плевать хотели, что ты отменил, после обновления страницы, возвращаются на место. Я решил, что бороться следует с этим через unset . Я добавил строчку.

If($res = $db->setQuery($query)->loadAssoc()) { $session->set("user", $res); } else { unset($_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"]); header("WWW-Authenticate: Basic realm="My Realm""); header("HTTP/1.0 401 Unauthorized"); }

Я старался совладать с этими переменными, но всё глубже уходил в никуда. Устраивал и проверку существования сессии, но тщетно. К тому же мне требовалось сделать завершение сессии, что с слов форумчан мало представляется возможным. Докопался до истины использования адреса вида login :pass@locahost/. Замечательно, переменные изменились $_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"] . Увы, но это не стало моим окончательным решением, поскольку после окончания времени сессии $_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"] продолжали исполнять. Как и после принудительно присваивания $session->set("user", null). Я вне себя от гнева, но знал, что не прощу себе, если позволю отступиться. Я написал отдельное условие для проверки на логаут.

If($_SERVER["PHP_AUTH_USER"]=="logout"){ $session->set("user", null); header("Refresh: 0;URL="); } if(!isset($_SERVER["PHP_AUTH_PW"])) { header("WWW-Authenticate: Basic realm="My Realm""); header("HTTP/1.0 401 Unauthorized"); } else { //В случае с обнаружением подходящего codeword - создаём сессию if($session->get("user") === null) { $db = JFactory::getDbo(); $query = $db->getQuery(true); $query->select("*"); $query->from("#__beda_users"); $query->where("codeword = ".$query->quote($_SERVER["PHP_AUTH_PW"])); if($res = $db->setQuery($query)->loadAssoc()) { $session->set("user", $res); } else { unset($_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"]); header("WWW-Authenticate: Basic realm="My Realm""); header("HTTP/1.0 401 Unauthorized"); } } else { //Нам бы сюда } }

Условие сработало, однако после перезагрузки страницы, когда появляется окно с требованием ввести имя пользователя и пароль , оно их приняло, да после обновление страницы, он предложил мне еще раз ввести пароль, нажму «Отмена», $_SERVER["PHP_AUTH_USER"] будет logout. Обновлю значения, он присвоит их. А нажму на отмену от вернёт прежние значения. Беда .

В конце концов окончательное решение выглядит так.

$session = JFactory::getSession(); function http_auth($session){ $session->set("user", null); unset($_SERVER["PHP_AUTH_PW"], $_SERVER["PHP_AUTH_USER"]); header("WWW-Authenticate: Basic realm="Auth""); header("HTTP/1.0 401 Unauthorized"); } if($_SERVER["PHP_AUTH_USER"]=="logout"){ $session->set("user", null); header("Refresh: 0;URL="); } if($session->get("user") === null){ if(!isset($_SERVER["PHP_AUTH_PW"])){ http_auth($session); } else { $pw = $_SERVER["PHP_AUTH_PW"]; $db = JFactory::getDbo(); $query = $db->getQuery(true); $query->select("*"); $query->from("#__beda_users"); $query->where("codeword = ".$query->quote($pw)); if($res = $db->setQuery($query)->loadAssoc()){ $session->set("user", $res); } else { http_auth($session); } } } else { if(!isset($_SERVER["PHP_AUTH_PW"])){ http_auth($session); } }

Возможно использовать функцию header() для отправки сообщения "Authentication Required" браузеру, заставив его показать окошко для ввода логина и пароля. Как только пользователь заполнит логин и пароль, ссылка, содержащая PHP-скрипт будет вызвана еще раз с предопределенными переменными PHP_AUTH_USER , PHP_AUTH_PW , и AUTH_TYPE , установленными в логин, пароль и тип аутентификации соответственно. Эти предопределенные переменные хранятся в массивах $_SERVER и $HTTP_SERVER_VARS . Поддерживаются оба типа: "Basic" и "Digest" (начиная с версии PHP 5.1.0). Подробнее смотрите функцию header() .

Пример фрагмента скрипта, который вынуждает клиента авторизоваться для просмотра страницы:

Пример #1 Пример Basic HTTP-аутентификации

if (!isset($_SERVER [ "PHP_AUTH_USER" ])) {
header ("WWW-Authenticate: Basic realm="My Realm"" );

echo "Текст, отправляемый в том случае,
если пользователь нажал кнопку Cancel"
;
exit;
} else {
echo
"

Hello { $_SERVER [ "PHP_AUTH_USER" ]} .

" ;
echo "

Вы ввели пароль { $_SERVER [ "PHP_AUTH_PW" ]} .

" ;
}
?>

Пример #2 Пример Digest HTTP-аутентификации

Это пример реализации простого скрипта Digest HTTP-аутентификации. За подробностями обращайтесь к » RFC 2617 .

$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("Неправильные данные!" );

// ok, логин и пароль верны
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_AUTH не устанавливаются в случае, если данная страница использует внешнюю аутентификацию и установлен безопасный режим . Несмотря на это, переменная REMOTE_USER может использоваться для аутентификации пользователя, прошедшего внешнюю аутентификацию. Таким образом, вы всегда можете воспользоваться переменной $_SERVER["REMOTE_USER"] .

Замечание : Замечание касательно конфигурации

PHP использует указание директивы AuthType для указания того, используется внешняя аутентификация или нет.

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

И Netscape Navigator и Internet Explorer очищают кэш аутентификации текущего окна для заданного региона (realm) при получении от сервера статуса 401. Это может использоваться для реализации принудительного выхода пользователя и повторного отображения диалогового окна для ввода имени пользователя и пароля. Некоторые разработчики используют это для ограничения авторизации по времени или для предоставления кнопки "Выход".

Пример #3 Пример HTTP-аутентификации с принудительным вводом новой пары логин/пароль

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 "

Добро пожаловать: " . htmlspecialchars ($_SERVER [ "PHP_AUTH_USER" ]) . "
" ;
echo "Предыдущий логин: " . htmlspecialchars ($_REQUEST [ "OldAuth" ]);
echo "

\n" ;
echo "\n" ;
echo ". htmlspecialchars ($_SERVER [ "PHP_AUTH_USER" ]) . "\" />\n" ;
echo "\n" ;
echo "

\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 (значение по умолчанию).

Замечание :

В случае, если используется безопасный режим , UID текущего скрипта будет добавлен в realm -часть заголовка WWW-Authenticate .

Вступление

Это - обучающая программа которая должна вам показать основы защищиты ваших страниц в сети, использующие HTTP аутентификацию. Вместо традиционного.htaccess метода (Apache сервер), мы собираемся использовать для хранения данных о пользователях и их пароли в MySQL. Я постараюсь максимально разжевать все на, что по моему разумению требуется для начинающего изучать MySQL и PHP. В принципе на основе этой проги вы можите использовать любой DBMS (система управления базы данных). Почему интересен этот метод? Ну например хотя бы потому что, если Вы используете базу данных, вы можите с легкостью разрешить, только определенной группе (человеку) иметь определенныйе права для доступа к той или иной информации. Если Вы используете традиционный.htaccess метод Апач, Вы должны вручную добавлять пользователей и пароль в файле пароля. А приимущество данного метода, ну....взгляните сами.

Программное обеспечение которое необходио:

· *nix платформа (Linux, Unix, *BSD) · PHP 3.0.x или PHP 4.x · MySQL (любая версия)

Шаг номер один

Вперед, первое что надо это выяснить что мы хотим позволить пользователям, которые находится в нашей базе данных, чтобы получить доступ к указанной странице? И как мы собираемся это сделать? (многим не очень нравится, но надо привыкать перед программированием брать бумажку и записывать все требования, которые мы хотим получить от проги, в перспективе вы сэкономите часы а может дни, для внесения изменений в код (прим.))

Проверить, заверен ли пользователь уже.

Если нет, отправить сообшение в броузер, с сообщением и формой для доступа.

Если пользователь княпает на кнопку отмены, не позволить ему доступ и переадресовывать его идти на... 403: Доступ отвергнут, или показать (кукиш J) простое сообщение.

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

Если Вы не поняли все не волнуйтесь, станет ясно позже (а может никогда)!

Шаг Два - Создаем Нашу Базу данных

Мы хотим, чтобы база данных хранила имена (login) и пароль наших пользователей. Требуемые поля могут легко быть добавлены к существующей базе данных, но мы предположим пока, что Вы не добавляете к уже имеющейся базе а создаете новую. Следующий код это описание того как это сделать. Предположение если у вас на компе стоит Апач совсем что надо, можете немедленно приступить:)

mysql> create database members;
mysql> create table users (
username varchar(25) NOT NULL,
password varchar(15) NOT NULL,
primary key (username),
unique username (username)
);

Мы теперь имеем базу данных, чтобы хранить в ней пользователей, она предполагает, что username до 25 знаков, и пароли до 15 знаков. (если вам по каким-то причинам не подходит, установите как посчитаете Нужным) Username должен иметь значение "первичный ключ" и быть "уникальным", так как мы не хотим чтоб 2 или больше людей имели одинаковый username.

Пожалуйста обратите внимание, что usernames будет чувствитен к следующему случаю, пользователь "Vasya" будет идентифицирован другим, нежели пользователь "vasya", проще говоря чувствителен к регистру. Теперь мы добавим в MySQL тестового пользователя, чтобы использовать его дянные для тестов, когда мы создадим PHP страницу.

mysql> grant select on members.users
to httpuser@localhost
identified by "MyPassword";

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

mysql> insert into users value("john_doe", "eod_nhoj");

Я сознательно в проге не шифровал данные, для того, чтоб в случае утери пароля не дешифровать его, и упростить до минимума получения оного:)) Все, с MySQLпокончено теперь идем дальше!

Шаг Три - пишем PHP код

Прежде, чем мы начинаем, я опишу в кратце то, что будет делать пага. Когда Вы попадете на защищенную страницу то сервер пошлет запрос и выведет страницу для введения имени и пароля. Если вы нажмете на кнопку отмены или введете не правельные данные то сервер отправит вам (401 Неправомочный удар головой, и будет отрицать доступ.) - так переводит промпт обычно строку (401 Unauthorized header, and deny access) не буду пояснять по моему лучше не скажешь!!! При случае если вы все введете как надо, то окажется что просто напросто вы получите доступ (то что и требовалось доказать) Теперь самое веселое, это и есть тот самый код. Он написан сознательно с номерами строк, после кода (внизу) даны пояснения к строкам.

01 02
03 function access_denied() {
04 echo "401 Unauthorized: The username / password combination you entered was invalid.n";
05 }
06
07 function auth_headers($title) {
08 Header("WWW-Authenticate: Basic realm="$title"");
09 Header("HTTP/1.0 401 Unauthorized");
10 }
11
12 if(!isset($PHP_AUTH_USER)) {
13 auth_headers("My Protected Web Page");
14 access_denied();
15 exit;
16 }
17 else {
18
19 $hostname = "localhost";
20 $username = "httpuser";
21 $password = "MyPassword";
22 $database = "members";
23
24 $query = "select username,password from users where username="$PHP_AUTH_USER" and password="$PHP_AUTH_PW"";
25 $link = mysql_connect($localhost, $username, $password) or die("Unable to connect to database server");
26
27 if (mysql_num_rows(mysql_db_query($database, $query)) == 0) {
28 auth_headers("My Protected Web Page");
29 access_denied();
30 exit;
31 }
32
33 mysql_close($link);
34 }
35 ?>

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

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

Строка 3:
Эта функция покажет сообщение, если "злой юзер" упорно будет вводить левые данные. Я сделал это функцией, потому что используем ее дважды, и просто чтоб сократить исходный код.

Строка 7:
Так как мы используем этот заголовок тоже дважды я также сделал это функцией.

Строка 8:
Передать броузеру заголовок, который заставит таки юзера ввести логин и пароль. Переменная $title будет показана в login диалоге.

Строка 9:
При первом запросе выводится заголовок при повторной отмене выводит сообщение о запрете доступа.

Строка 12:
$PHP_AUTH_USER цикл который выводит сообщение о том что мол пага защищена, и убирайся вон!

Строка 19-23:
Это то что кроме вас никто не знает, то есть средства для коннекта с базой данных, имя хоста, имы базы, имя юзера, и пароль. (для соеденения с MySQL)

Строка 24:
Запрос к MySQL который возвращает имена и пароли.

Строка 25:
Установить связь с MySQL и вывести ругательство если связи не будет!!! (это значит что у вас что-то не то в строках 19-23, или вообще нет MySQL)

Строка 27:
Обработать $query. Если возвращет - 0, это означает, что была введена недействительная комбинация.

Строка 33:
Разъединить соеденение с MySQL.

Я рекомендовал бы сохранить PHP код в файле под наванием user_auth.php, user_auth.php3, или... (тут ваша фантазия на эту тему) Предположим, что таки сохранили этот код в файле user_auth.php. Всякий раз, когда мы захотим вдруг защитить нашу сверхсекретную пагу в сети, мы просто подключаем этот файл. Единственное на что хочется обратить внимание, что по логике надо подключать в самой верхней части своей защищенной PHP страницы, советую в строке номер 1 ваше паги написать следующее:

где "user_auth.php" это имя файла под которым вы сохранили код.

Ваш вопрос - я не использую MySQL, как быть?

Посоветуйтесь с админом вашего сервера, если он окажется добрым, то он вам поможет, для него это 5 минут работы, если злой то не поможет, тогда идите на форум относящийся к той БД которую вы исьпользуете и кричите о помощи! Или если вы считаете себя нормальным программером, то...вам вообще этот код не понадобиться, и вы будите создавать "сессии", шифровать с помощью PGP вобщем извращаться так, как быдто вы делаете защиту для amazon.com

Возможно использовать функцию header() для посылки сообщения "Authentication Required" браузеру, заставив его показать окошко для ввода логина и пароля. Как только пользователь заполнит логин и пароль, ссылка, содержащая PHP-скрипт будет вызвана еще раз с предопределенными переменными PHP_AUTH_USER , PHP_AUTH_PW , и AUTH_TYPE , установленными в логин, пароль и тип аутентификации соответственно. Эти предопределенные переменные хранятся в массивах $_SERVER и $HTTP_SERVER_VARS . Поддерживаются оба типа: "Basic" и "Digest" (начиная с версии PHP 5.1.0). Подробнее смотрите функцию header() .

Пример фрагмента скрипта, который вынуждает клиента авторизироваться для просмотра страницы:

Пример #6 Пример Basic HTTP-аутентификации

if (!isset($_SERVER [ "PHP_AUTH_USER" ])) {
header ("WWW-Authenticate: Basic realm="My Realm"" );

echo "Текст, отправляемый в том случае,
если пользователь нажал кнопку Cancel"
;
exit;
} else {
echo
"

Hello { $_SERVER [ "PHP_AUTH_USER" ]} .

" ;
echo "

Вы ввели пароль { $_SERVER [ "PHP_AUTH_PW" ]} .

" ;
}
?>

Пример #7 Пример Digest HTTP-аутентификации

Это пример реализации простого скрипта Digest HTTP-аутентификации. За подробностями обращайтесь к » RFC 2617 .

$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("Неправильные данные!" );

// ok, логин и пароль верны
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 4.3.0, для того, чтобы предотвратить написание кем-либо скрипта, раскрывающего пароль к странице, которая использует внешнюю аутентификацию, переменные PHP_AUTH не устанавливаются в случае, если данная страница использует внешнюю аутентификацию и установлен безопасный режим . Несмотря на это, переменная REMOTE_USER может использоваться для аутентификации пользователя, прошедшего внешнюю аутентификацию. Таким образом, вы всегда можете воспользоваться переменной $_SERVER["REMOTE_USER"] .

Замечание : Замечание касательно конфигурации

PHP использует указание директивы AuthType для указания того, используется внешняя аутентификация или нет.

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

И Netscape Navigator и Internet Explorer очищают кэш аутентификации текущего окна для заданного региона (realm) при получении от сервера. Это может использоваться для реализации принудительного выхода пользователя и повторного отображения диалогового окна для ввода имени пользователя и пароля. Некоторые разработчики используют это для ограничения авторизации по времени или для предоставления кнопки "Выход".

Пример #8 Пример HTTP-аутентификации с принудительным вводом новой пары логин/пароль

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 "

Добро пожаловать: " . htmlspecialchars ($_SERVER [ "PHP_AUTH_USER" ]) . "
" ;
echo "Предыдущий логин: " . htmlspecialchars ($_REQUEST [ "OldAuth" ]);
echo "

\n" ;
echo "\n" ;
echo ". htmlspecialchars ($_SERVER [ "PHP_AUTH_USER" ]) . "\" />\n" ;
echo "\n" ;
echo "

\n" ;
}
?>

Это поведение не регламентируется стандартами HTTP Basic -аутентификации, следовательно, вы не должны зависеть от этого. Тестирование браузера Lynx показало, что Lynx не очищает кэш авторизации при получении от сервера статуса 401, и, нажав последовательно "Back", а затем "Forward" возможно открыть такую страницу, при условии, что требуемые атрибуты авторизации не изменились. Однако, пользователь может нажать клавишу "_" для очистки кеша аутентификации.

Также следует заметить, что до версии PHP 4.3.3, HTTP-аутентификация не работала на серверах под управлением Microsoft IIS, если PHP был установлен как CGI-модуль, в силу некоторых ограничений IIS. Для того, чтобы добиться корректной работы в PHP 4.3.3+, вы должны отредактировать конфигурационную настройку IIS под названием "Directory Security ". Щелкните на надписи "Edit " и установите опцию "Anonymous Access ", все остальные поля должны остаться неотмеченными.

Еще одно ограничение, если вы используете IIS посредством ISAPI и PHP 4: переменные PHP_AUTH_* не определены, но в то же время доступна переменная HTTP_AUTHORIZATION . Пример кода, который вы могли бы использовать: list($user, $pw) = explode(":", base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6)));

Замечание : Замечание касательно IIS:
Для того, чтобы HTTP-аутентификация корректно работала в IIS, в конфигурации PHP опция cgi.rfc2616_headers должна быть установлена значением 0 (значение по умолчанию).

Замечание :

В случае, если используется безопасный режим , UID текущего скрипта будет добавлен в realm -часть заголовка WWW-Authenticate .

Эта статья также доступна на следующих языках: Тайский

  • Next

    Огромное Вам СПАСИБО за очень полезную информацию в статье. Очень понятно все изложено. Чувствуется, что проделана большая работа по анализу работы магазина eBay

    • Спасибо вам и другим постоянным читателям моего блога. Без вас у меня не было бы достаточной мотивации, чтобы посвящать много времени ведению этого сайта. У меня мозги так устроены: люблю копнуть вглубь, систематизировать разрозненные данные, пробовать то, что раньше до меня никто не делал, либо не смотрел под таким углом зрения. Жаль, что только нашим соотечественникам из-за кризиса в России отнюдь не до шоппинга на eBay. Покупают на Алиэкспрессе из Китая, так как там в разы дешевле товары (часто в ущерб качеству). Но онлайн-аукционы eBay, Amazon, ETSY легко дадут китайцам фору по ассортименту брендовых вещей, винтажных вещей, ручной работы и разных этнических товаров.

      • Next

        В ваших статьях ценно именно ваше личное отношение и анализ темы. Вы этот блог не бросайте, я сюда часто заглядываю. Нас таких много должно быть. Мне на эл. почту пришло недавно предложение о том, что научат торговать на Амазоне и eBay. И я вспомнила про ваши подробные статьи об этих торг. площ. Перечитала все заново и сделала вывод, что курсы- это лохотрон. Сама на eBay еще ничего не покупала. Я не из России , а из Казахстана (г. Алматы). Но нам тоже лишних трат пока не надо. Желаю вам удачи и берегите себя в азиатских краях.

  • Еще приятно, что попытки eBay по руссификации интерфейса для пользователей из России и стран СНГ, начали приносить плоды. Ведь подавляющая часть граждан стран бывшего СССР не сильна познаниями иностранных языков. Английский язык знают не более 5% населения. Среди молодежи — побольше. Поэтому хотя бы интерфейс на русском языке — это большая помощь для онлайн-шоппинга на этой торговой площадке. Ебей не пошел по пути китайского собрата Алиэкспресс, где совершается машинный (очень корявый и непонятный, местами вызывающий смех) перевод описания товаров. Надеюсь, что на более продвинутом этапе развития искусственного интеллекта станет реальностью качественный машинный перевод с любого языка на любой за считанные доли секунды. Пока имеем вот что (профиль одного из продавцов на ебей с русским интерфейсом, но англоязычным описанием):
    https://uploads.disquscdn.com/images/7a52c9a89108b922159a4fad35de0ab0bee0c8804b9731f56d8a1dc659655d60.png