Если вы пользуетесь ядром СУБД MySQL, таблица пользователей будет строиться по приведенной ниже схеме.
-
CREATE TABLE auth_user{
-
user_id varchar(32) NOT NULL,
-
username varchar(32) NOT NULL,
-
password varchar(32) NOT NULL,
-
perms varchar(255),
-
PRIMARY KEY (user_id),
-
UNIQUE k_username (username)
-
};
Первичным ключом является поле user_id, потому что внутренние процедуры библиотеки PHPLib работают именно с идентификационным номером пользователя, а не с парой значений "имя пользователя - пароль" (username/password). Пользовательский идентификатор (который в библиотеке PHPLib называется uid) представляет собой уникальную строку, аналогичную идентификатору сеанса, которая создается функциями uniqid() и md5(), как показано ниже.
$uid = md5(uniqid($hash_secret));
Почему в библиотеке PHPLib не используется составной первичный ключ, включающий в себя поля username и password? Ведь в этом случае нам удалось бы сэкономить место за счет того, что отпадает необходимость в дополнительном поле user_id. Причина заключается в том, что основными задачами библиотеки PHPLib являются обеспечение возможности применения произвольной процедуры аутентификации и упрощение интерфейса. Наличие у каждого пользователя отдельного уникального идентификатора фиксированной длины упрощает создание дополнительных таблиц, привязанных в модели связей базы данных к таблице auth_user.
В последнем примере мы просто использовали заданную по умолчанию реализацию класса Auth, которая предлагается дистрибутивом библиотеки PHPLib в сценарии Example_Default_Auth. Вам почти всегда придется создавать собственные классы, расширяя базовый класс Auth. В исходном виде класс Auth не используется, потому что в нем нет двух функций, необходимых для аутентификации. Класс Auth не знает, какой вы хотите использовать экран регистрации и как именно вы хотите осуществлять аутентификацию. Вы должны сами определять соответствующие функции в производных классах. В листинге 6.5 представлен пример такого производного класса; этот класс мало чем отличается от образца реализации, приведенного в файле local.inc.
Листинг 6.5. Расширение базового класса Auth
-
require("EasyTemplate.inc.php3);
-
class My_Auth extends Auth
-
{
-
var $classname = "My_Auth";
-
var $database_class = "DB_Example";
-
var $database_table = "auth_user";
-
function auth_lpginform()
-
{
-
//создать экземпляр шаблона
-
$tpl = new EasyTemplate("loginform.inc.html");
-
//задано ли имя пользователя? Если да, это значит,
-
//что первая попытка аутентификации не удалась
-
if(isset($this->auth["uname"]))
-
{
-
$tpl->assign("USERNAME", $this->auth["uname"]);
-
$tpl->assign("MESSAGE", "Либо имя, либо пароль заданы
-
неверно.
Попробуйте еще раз!");
-
}
-
else
-
{
-
$tpl->assign("USERNAME", "");
-
$tpl->assign("MESSAGE", "Пожалуйста, введите свое имя и пароль:");
-
}
-
$tpl->assign("ACTION", $this->url());
-
//вывести результаты синтаксического анализа шаблона
-
$tpl->easy_print();
-
}
-
function auth_validatelogin()
-
{
-
//глобальные переменные формы
-
global $username, $password;
-
//если существует значение $username, запомнить его
-
if(isset($username))
-
{
-
$this->auth["uname"] = $username;
-
}
-
//установить значение $uid равным false по умолчанию
-
$uid = false;
-
//выбрать строки, соответствующие введенным
-
//имени пользователя и паролю
-
$query = "
-
SELECT
-
*
-
FROM
-
$this->database_table
-
WHERE
-
username = '$username'
-
AND password = '$password'
-
";
-
//выполнить запрос
-
$this->db->query($query);
-
//если возвращена одна строка, пользователь
-
//считается прошедшим аутентификацию
-
if($this->db->num_rows() == 1)
-
{
-
$this->db->next_record();
-
//задать $uid и массив $this->auth
-
$uid = $this->db->Record["user_id"];
-
$this->auth["uid"] = $uid;
-
$this->auth["uname"] = $this->db->Record["username"];
-
}
-
return($uid);
-
}
-
}
Две переменные класса Auth: $database_class и $database_table - используются классом как внутренние для хранения информации о сеансе и данных аутентификации. Они не влияют на процесс аутентификации. Процедура регистрации обеспечивается двумя методами класса, которые необходимо определить, - auth_ loginform() и auth_validatelogin().
Если пользователь запрашивает защищенную страницу и еще не вошел в систему, класс Auth запускает функцию auth_loginform(). Эта функция должна вывести экран регистрации; в случае неудачной аутентификации она будет вызвана повторно. Следовательно, в ней должен быть предусмотрен механизм обработки неудачных попыток аутентификации. В нашем примере при неудачной аутентификации на экран выводится соответствующее сообщение, а поле формы, предназначенное для ввода имени пользователя, заполняется ранее введенными данными.
Вторая функция, auth_validatelogin(), фактически представляет собой сердце класса: именно здесь выполняется процедура аутентификации. Данная функция будет вызываться тогда, когда пользователь подтверждает правильность введенной им информации в форме, предъявленной пользователю функцией auth_loginform(). Переменные формы - это глобальные переменные, они должны быть объявлены в функции в качестве глобальных до того, как программа к ним обратится. Конкретная методика аутентификации полностью зависит от вас. В приведенном примере аутентификация проводится с помощью стандартной таблицы auth_user, предложенной в дистрибутиве библиотеки PHPLib, но вы вполне можете использовать файлы типа .htaccess, сервер LDAP и т. д.
Если аутентификация прошла успешно, функция должна вернуть правильный идентификатор пользователя и создать массив $this->array. Этот ассоциативный массив должен содержать по крайней мере два элемента: uid (уникальный идентификатор пользователя) и uname (имя пользователя, введенное им самим).
Если вы хотите использовать механизм уровней доступа класса Perm (подробнее об этом ниже), надо задать дополнительный элемент $this->auth["perm"]. Этот элемент должен содержать права доступа пользователя в виде списка имен, разделенных запятыми без пробелов, например admin или author,editor. Обычно этот список находится в той среде данных, из которой вы получаете информацию о пользователе, - в нашем примере это база данных MySQL.
Если в ходе аутентификации возникает ошибка, функция должна возвратить false; в этом случае функция auth_loginform() вызывается повторно. Обратите внимание, что мы устанавливаем значение $this->auth["uname"] независимо от того, насколько успешной была аутентификация. Массив $this->auth является переменной сеанса и сохраняется на протяжении всего процесса входа в систему независимо от количества попыток. В функции auth_loginform() мы проверяем, было ли введено имя пользователя, и заносим полученное имя в форму регистрации.
Теперь, когда пользователь правильно зарегистрировался в приложении, вы точно знаете, с кем имеете дело. Для управления различными уровнями прав доступа, ассоциированных с пользователями, вы можете использовать другой класс библиотеки PHPLib - Perm.