Доступ к базам данных средствами
PHP ч.3
|
В соответствующем
разделе главы 4 мы отмечали, что методика базовой
аутентификации HTTP имеет ряд недостатков, которые отсутствуют
в механизме аутентификации, предусмотренном в системе PHP. В
следующем разделе этот вопрос рассматривается более подробно.
-
Преимущества аутентификации
средствами PHP
В данном разделе
мы продолжим разговор об аутентификации с того места, где
остановились в главе 4. Мы уже рассмотрели недостатки метода
базовой аутентификации HTTP (HTTP Basic Authentication) и
отметили тот факт, что аутентификация на основе PHP этих
недостатков лишена. Библиотека PHPLib содержит сложные классы
для обработки данных аутентификации пользователей и управления
правами доступа.
Библиотека PHPLib
аутентифицирует сеансы, а следовательно, зависит от класса
Session. Для тех страниц, где требуется аутентификация,
необходимо произвести следующий вызов функции page_open() для
инстанцирования объекта сеанса и аутентификации.
page_open(array("sess" =>
"Session_Example", "auth" => "Auth_Example"));
Поскольку
данный механизм аутентификации базируется на концепции сеансов
работы пользователей, он имеет ряд преимуществ, перечисленных
ниже.
* Имя
пользователя и элемент аутентификации пересылаются только один
раз, в начале сеанса. После успешной аутентификации сервер
хранит дату аутентификации внутри сеанса и больше не передает
имя пользователя и элемент аутентификации. Для сравнения: при
базовой аутентификации HTTP имя пользователя и пароль
передаются в заголовках HTTP каждого запроса. Однако если вы
теряете сеанс в PHP, то вы теряете аутентификацию.
*
Процедура аутентификации на сервере может быть сложной. В ней
может использоваться база данных или другой аналогичный
механизм. Аутентификация выполняется неопределенной функцией
auth_validatelogin() класса Auth. Реализация этой функции за
вами.
*
Данная методика не ограничена уровнем доступа к папкам;
механизм аутентификации может быть различным для отдельных
файлов приложения и даже для разных уровней приложения внутри
одного сценария. Какие-то части сценария можно скрыть от не
имеющих к ним доступа пользователей.
*
Пользователи, не известные системе, могут зарегистрироваться
перед началом процедуры входа в систему. Пользователю
предлагается соответствующая форма, и библиотека PHPLib
автоматически создает для нового пользователя стандартную
запись в базе данных о пользователях.
*
Аутентификация работает даже в версии программы PHP на основе
CGI.
* Вы
можете организовать для пользователей явный выход из системы.
Это означает, что пользователи имеют возможность явным образом
завершить текущий сеанс (предусмотрена кнопка выхода из
системы).
*
Сеанс работы пользователя может быть завершен автоматически по
истечении заданного времени ожидания. Это обеспечивает
дополнительный уровень защиты данных приложения, поскольку вы
можете по истечении времени ожидания предотвратить
несанкционированный доступ к данным сеанса.
-
Пример использования класса Auth
В примере,
приведенном в листинге 6.4, вы встретитесь с заданным по
умолчанию в библиотеке PHPLib видом экрана регистрации, или
входа пользователя в систему. Именно так будет выглядеть экран
регистрации при первом обращении к нему. Войдите в систему с
заданными в библиотеке PHPLib по умолчанию именем пользователя
и паролем (kris/test). По завершении аутентификации вы увидите
идентификатор сеанса, ваше пользовательское имя и права
доступа.
Листинг 6.4. Простейший пример работы с
экраном аутентификации
page_open(array("sess" =>
"Session_Example", "auth" => "Auth_Example"));
printf("Идентификатор сеанса: %s
\n", $sess->id);
printf("Идентификатор пользователя: %s
\n", $auth->auth["uid"]);
printf("Ваше
входное имя: %s
\n", $auth->auth["uname"]);
printf("Ваши
права доступа: %s
\n", $auth->auth["perm"]);
page_close()
Все
страницы, использующие механизм аутентификации,
предусмотренный в библиотеке PHPLib, придерживаются этой общей
структуры. Сначала вызывается функция page_open(); остальная
часть сценария будет выполняться только после входа
пользователя в систему и завершения его аутентификации. Вы
вполне можете быть уверены в том, что ни один пользователь,
если он не прошел регистрацию, не увидит ничего,
расположенного в тексте сценария после вызова функции
page_open(). Написав всего одну строку кода, вы обеспечиваете
в своем сценарии полную аутентификацию пользователя. После
того как вы решили, какие классы вы хотите включить в
приложение, библиотеку PHPLib использовать действительно
просто. До сих пор во всех примерах мы применяли готовые
классы, поставляемые в составе библиотеки PHPLib. Однако вам
придется создавать свои собственные классы (производные от
базовых), соответствующие вашим задачам. Для этого необходимо
лучше разобраться в принципах работы библиотеки PHPLib.
-
Внутренние переменные класса Auth
Если вы
пользуетесь ядром СУБД 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",
"Либо имя, либо пароль заданы
неверно. <br>
Попробуйте еще раз!");
}
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.
-
Управление уровнями прав доступа
Типичное
приложение обычно имеет два уровня прав доступа: пользователя
и администратора. Однако в некоторых приложениях необходим
более сложный механизм управления доступом. Например,
текстовые базы данных требуют множества уровней прав доступа.
*
Супервизор может изменять в системе все, что требуется, может
модифицировать пользовательскую систему и т. д.
*
Редактор может редактировать статьи и другую информацию, а
также утверждать тексты, предлагаемые авторами.
*
Автор может создавать статьи и другие виды текстов, вносить их
на рассмотрение редакторов, но не может сам утверждать тексты;
*
Пользователь располагает лишь правами доступа для чтения.
Поскольку вы
знаете текущего зарегистрированного пользователя и можете
идентифицировать его по уникальной строке ($uid), то несложно
написать функции, которые будут включать пользователя в
определенную группу и предоставлять ему те или иные права
доступа в зависимости от того, что это за группа. Библиотека
PHPLib располагает встроенными функциями для выполнения этих
действий.
Для того чтобы
можно было работать с классом Perm, вы должны добавить еще
один элемент к вызову функции page_open(). Библиотека PHPLib
по умолчанию предоставляет реализацию класса Perm с именем
Example_Perm. Но вы уже знаете, как следует поступить, чтобы
можно было использовать все возможные функции, как привести
систему в соответствие со своими потребностями, - необходимо
создать собственный производный клаcс в файле local.inc.
В листинге 6.6
приведен пример использования класса Perm. Здесь реализовано
несколько больше функциональных возможностей, чем
действительно необходимо: наш класс позволяет выходить из
системы и повторно входить в нее с другим именем пользователя
(это позволяет более наглядно продемонстрировать механизм
уровней прав доступа в действии); эталонный пользователь
PHPLib (имя пользователя kris, пароль test) получает
привилегии администратора (admin), и если вы войдете в систему
под этим именем, сценарий выведет сообщение "Добро пожаловать,
администратор". Поскольку в дистрибутиве библиотеки PHPLib
задан единственный пользователь - администратор, - нужно
создать и других пользователей, чтобы увидеть, как выглядит
соответствующая страница для посетителей с иным уровнем
доступа.
Листинг 6.6. Работа с классом Perm
page_open(array("sess" => "
Example_Session", "auth" => "Example_Auth
", "perm" => "Example_Perm"));
if(isset($mode) && $mode == "reload")
{
$auth->unauth();
print("Вы успешно вышли из
системы.
");
printf('Если хотите, вы можете
<a href=%s">
войти повторно.',
е$sess->url(basename($PHP_SELF)));
}
else
{
if($perm->have_perm("admin"))
{
print("<b>Добро пожаловать,
администратор.</b><br>");
print('Вы вошли в систему с уровнем доступа
"admin".<br>');
}
else
{
printf(Вы вошли в систему с уровнем доступа
"%s".<br>',
е$auth->auth["perm"]);
}
printf("Ваше
имя: $s<br>", $auth->auth["name"]);
printf('<a href=%s">Log
out</a>',
е$sess->url(basename($PHP_SELF)."?mode=reload"));
}
page_close();
Поразрядные
вычисления часто вызывают большие затруднения у
программистов-новичков, и даже опытные разработчики
периодически испытывают трудности при работе с ними.
Однако
представление значений флагов с помощью отдельных битов часто
бывает очень удобным и полезным способом организации
информации. Так, в библиотеке PHPLib этот прием используется
для уровней прав доступа. Часто для хранения значений флагов
используется целочисленное поле (INT) базы данных. Рассмотрим
приложение, которое должно обеспечивать возможность обработки
и сохранения неопределенного количества данных, например обо
всех увлечениях пользователя. Вместо того чтобы создавать в
базе данных отдельные поля для каждого определенного в
программе вида хобби и устанавливать их значения равными false
или true, можно применить единое поле, состоящее из битовых
флагов. В зависимости от того, входит ли некоторое хобби в
число увлечений пользователя, соответствующий бит
устанавливается или сбрасывается - "включается" или
"выключается".
Поразрядные
операции - это операции, которые выполняются над одним или
несколькими битами. Вы знаете, что в двоичной системе
счисления используется понятие октета битов -
последовательности из восьми двоичных цифр (нулей или единиц).
Десятичное число 42 в двоичной системе представляется как
00101010:
Позиция бита: 7 6 5 4 3 2 1 0
Значение бита: 0 0 1 0 1 0 1 0
Самый правый бит,
нулевой, называется младшим значащим битом (разрядом). Бит № 7
называется старшим значащим битом (разрядом). Чтобы
преобразовать число из двоичной системы в десятичную и
наоборот, можно использовать функции языка PHP BinDec() и
DecBin() соответственно.
Двоичные
операторы устанавливают и снимают определенные биты в октетах.
Установка значения бита
Чтобы установить
определенный бит, используется операция включающей дизъюнкции
(значение | значение). Допустим, текущее значение флага $value
равно 3 (это означает, что установлен нулевой и первый биты),
а вы хотите дополнительно установить второй бит (не забывайте,
что нумерация начинается с нуля). Тогда можно воспользоваться
операцией включающей дизъюнкции текущего значения флага с
константой 4 (2 во второй степени):
$value = 3;
$value |= 4;
Теперь значение
стало равно 7. В двоичном виде операция выглядит следующим
образом:
0 0 0
0 0 1 1
| 0 0
0 0 1 0 0
= 0 0
0 0 1 1 1
Переключение бита
Переключение бита
- установка его значения равным 1, если он был равен 0, и
наоборот, - осуществляется операцией исключающей дизъюнкции
(value ^ value). Если значение равно 3, а мы хотим переключить
первый бит (который равен 1, поскольку в двоичной системе
счисления число 3 выглядит как 0000011), то следует написать:
$value = 3;
$value ^= 2;
В результате
получится 1. В двоичном виде:
0 0 0
0 0 1 0
^ 0 0
0 0 0 1 0
= 0 0
0 0 0 0 1
Сброс
бита
Сброс бита
осуществляется очень просто: сначала нужно убедиться, что он
включен, а затем обратить его. Это требует двух поразрядных
операций (value & ~value). Чтобы сбросить первый бит в
значении 3, можно использовать следующие строки:
$value = 3;
$value $= ~2;
Проверка значения бита
Чтобы проверить,
установлен ли бит, используется операция конъюнкции. Эта
операция сравнивает два значения и возвращает 1 для тех
позиций, где биты в обоих числах оказались равны 1. Скажем,
чтобы проверить, установлен ли первый бит в константе 3, можно
написать:
if(2
& 3)
//соответствующий код
Поразрядный сдвиг
Для сдвига битов
вправо или влево можно использовать операторы сдвига >>
и << (например, значение << количество_позиций).
Так, сдвиг значения 1 влево на одну позицию даст в результате
двоичное значение 10:
0 0 0
0 0 0 1
<< 0 0 0 0 0 1 0
= 0 0
0 0 0 1 0
Поразрядный сдвиг
может использоваться для установки значений битов (см.
пример).
Приоритет операторов
Помните, что
приоритет поразрядных операторов ниже, чем приоритет
арифметических операторов. Операторы в выражении 1 + 2 | 3
будут выполняться в следующем порядке: (1 + 2) | 3. Кроме
того, необходимо помнить, что поразрядные операторы имеют
более низкий приоритет, чем операторы сравнения. Будьте
внимательны и избегайте условий вроде if(2 & 3 != 0).
Вместо проверки на то, установлен ли второй бит в значении 3
(а он установлен), в данном выражении сначала проверяется
значение условия 3 != 0, а это, конечно, правда (true). В
результате мы получаем выражение 2 & 1, возвращающее 0, а
это совсем не то, что мы хотели.
Пример
Вернемся к
примеру с увлечениями пользователя, который мы использовали
выше. Предположим, что в программе определены четыре возможных
увлечения: чтение, программирование, сочинительство и
путешествия. В начале каждому хобби мы поставим в соответствие
свой бит:
*
чтение - 0
*
программирование - 1
*
сочинительство - 2
*
путешествия - 3
В двоичном виде
эти значения представлены следующим образом:
Чтение: 0 0 0 0 0 0 1
Программирование:
0 0 0 0 0 1 0
Сочинительство: 0 0 0 0 1 0 0
Путешествия: 0 0 0 1 0 0 0
Определить виды
увлечений в тексте сценария можно обычным поразрядным сдвигом:
define("HOBBY_READING":, 1 << 0);
define("HOBBY_PROGRAMMING", 1 << 1);
define("HOBBY_WRITING", 1 << 2);
define("HOBBY_HIKING", 1 << 3); Уровень
абстрактного представления базы данных
Переносимость
Режим отладки
Обработка ошибок
Пример использования
класса DB_Sql
Сеанс работы
пользователя
Запасной режим
повторной генерации идентификатора сеанса
Буферизация страниц
Сериализация
Работа с сеансами
Функция page_open()
Функции purl(), url()
и pself()
Аутентификация
Преимущества
аутентификации средствами PHP
Пример использования
класса Auth
Внутренние переменные
класса Auth
Управление уровнями
прав доступа
Поразрядные операции
Заключение
Если
пользователь выбирает в качестве хобби сочинительство и
программирование, можно создать комбинацию битов при помощи
оператора | (включающая дизъюнкция):
$pattern = HOBBY_WRITING |
HOBBY_PROGRAMMING;
После
этого вы можете проверить, действительно ли пользователь
выбрал сочинительство в качестве своего хобби, обратившись к
значению соответствующего бита:
printf ("Сочинительство %s выбрано.",
(HOBBY_WRITING & $pattern) ? "": "не");
Для сброса бита,
связанного с сочинительством, можно использовать следующую
строку:
$pattern &= -HOBBY_WRITING;
Проверка уровня
прав доступа осуществляется с помощью функции $auth->
have_perm("admin"). В качестве параметра ей передается уровень
прав доступа; в нашем примере это
$auth->have_perm("admin"). Функция проверяет, имеет ли
пользователь привилегию admin. Если пользователь имеет
необходимые права доступа, то функция возвращает true, иначе -
false.
У каждого
пользователя есть соответствующие привилегии. В реализации
класса Example_Auth информация о привилегиях записывается в
таблицу auth_user базы данных MySQL. Вы уже видели это поле в
текстах сценариев:
perms
varchar (255)
Список допустимых
уровней доступа определяется в классе, производном от Perm, в
переменной класса $permissions. Для класса Example_Perm
установлены следующие разрешения на доступ:
var $permissions = array(
"user" =>1
"author" =>2
"editor" =>4
"supervisor" =>8
"admin" =>16
);
Права доступа
переводятся в двоичные значения внутренними функциями класса;
при соответствующих вычислениях используются конъюнкция и
дизъюнкция. Значения в определенном выше ассоциативном массиве
определяют свою комбинацию битов для каждого уровня прав
доступа. Хотя все это выглядит достаточно сложно,
использование комбинации битов очень эффективно для
представления подобных данных. В частности, этот механизм дает
возможность работать с уровнями, наследующими права доступа
более низких уровней. Если вы хорошо продумали соответствующие
комбинации битов, уровень admin может автоматически получить
все привилегии уровня user.
У значений,
заданных по умолчанию, подобная модель поведения отсутствует:
уровень admin отличается от уровня user, и пользователь,
принадлежащий к группе admin, не получит доступа к
функциональным возможностям, установленным в элементе
$auth->have_perm("user"). Чтобы было понятнее, посмотрим,
как библиотека PHPLib вычисляет комбинации битов.
*
Допустим, определенные возможности доступны только для уровня
user. Этому уровню соответствует константа 1.
*
Пусть пользователю соответствует уровень доступа admin,
которому соответствует число 16.
*
Указанные операнды соединяются конъюнкцией, в результате
получается 0 (проверьте сами: print(16 & 1);). Результат
(0) не совпадает с константой, определенной для уровня user
(требуется 1), поэтому доступ невозможен.
Суть этих
вычислений заключается в том, что библиотека PHPLib проверяет,
установлен ли в комбинации разрядов, заданной в качестве
аргумента функции $perm-> have_perms(), бит,
соответствующий правам доступа данного пользователя. Такой
механизм дает возможность определять сложные комбинации прав
доступа.
Рассмотрим другой
пример. Предположим, что имеется четыре уровня прав доступа:
admin, editor_in_chief, editor и author (администратор,
главный редактор, редактор, автор). Вы хотите, чтобы редактор
(editor) не мог вносить на рассмотрение ответственных лиц
никаких материалов (это прерогатива автора - author), но все
прочие группы должны наследовать права доступа, установленные
для более низких уровней. Окончательно система полномочий
выглядит следующим образом:
*
admin : наследует editor_in_chief, editor, author
* editor_in_chief: наследует editor, author
*
editor
*
author
Чтобы вычислить
комбинацию битов для каждой группы пользователей, следует
начать с нижнего уровня, author, с комбинации 1 (означающей,
что установлен самый правый, нулевой бит). Если бы мы хотели,
чтобы редактор наследовал уровень автора, мы бы использовали
его комбинацию разрядов и установили следующий бит (1 | 2).
Однако в данном примере мы хотим разделить права этих двух
групп, поэтому мы задаем уровень editor как комбинацию
разрядов, дающую значение 2 (двоичное 10).
Теперь, если
редактор запрашивает страницу, доступную только для группы
author, он не получает к ней доступа:
*
Требуемый уровень (author): 1.
*
Действительный уровень (editor): 2.
*
Конъюнкция 1 и 2 (1 & 2) равна 0, а это не соответствует
требуемому уровню.
Следующий, более
высокий уровень (второй бит, то есть третий справа) - это
editor_in_chief, наследующий уровням editor и author. Это
означает, что в комбинации разрядов уровня главного редактора
должны быть установлены нулевой и первый биты, а мы
дополнительно устанавливаем второй бит (2 во второй степени,
или 4): 1 | 2 | 4. В результате получаем 7.
Проверим
правильность полученного результата:
*
Требуемый уровень (editor): 2.
* Текущий
уровень
(editor_in_chief): 7.
*
Конъюнкция 7 и 2 (7 & 2) дает 2, то есть требуемый
уровень.
Осталось
рассмотреть уровень администратора, который также наследует
всем низшим уровням. Следует использовать выражение 7 | 8
(константа 8, или 2 в третьей степени, используется для
установления третьего бита). Результат равен 15. Проверяем:
*
Требуемый уровень (editor_in_chief): 7.
*
Текущий уровень (admin): 15.
*
Конъюнкция 15 и 7 (15 & 7) дает нам 7, что соответствует
требуемому уровню.
Таким образом,
наши права доступа определяются следующим образом:
define("PHPLIB_PERM_AUTHOR", 1 | 0);
define("PHPLIB_PERM_EDITOR", 1 | 0);
define("PHPLIB_PERM_EDITOR_IN_CHIEF" 1 | 2 | 4);
define("PHPLIB_PERM_ADMIN", 1 | 2 | 4 | 8);
var $permissions = array(
"author" => PHPLIB_PERM_AUTHOR,
"editor" => PHPLIB_PERM_EDITOR,
"editor_in_chief" =>PHPLIB_PERM_EDITOR_IN_CHIEF,
"admin" => PHPLIB_PERM_ADMIN
);
В этой
статье вы познакомились с основными классами и способами
применения библиотеки PHPLib. Она является мощным
инструментом, обеспечивающим решение многих проблем, которые
неизбежно возникают при создании Web-приложений. Этой
библиотекой легко пользоваться, если вы позаботитесь о том,
чтобы предварительно создать на ее основе продуманный
механизм, отвечающий вашим потребностям. Библиотека PHPLib -
прекрасный каркас для реализации процедур управления всеми
аспектами сеансов работы пользователей и аутентификации.
В следующей главе
мы рассмотрим образец использования библиотеки PHPLib в
реальном приложении. Кроме того, вы познакомитесь еще с одним
классом - Template, - позволяющим добиться более полной
развязки кода и макета.