Статьи

Лучшая система входа в систему

Net.tuts + опубликовал несколько великолепных руководств по системам входа пользователей. Большинство учебных пособий посвящены только аутентификации пользователя, что обеспечивает два уровня безопасности: вход в систему и не вход в нее. Для многих сайтов требуется более высокий уровень контроля, чтобы контролировать, куда пользователи могут заходить и что они могут делать. Создание системы списка контроля доступа (ACL) предоставит вам гибкость для детальных разрешений.



Конечный продукт

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

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

Реализация списка контроля доступа позволит вам значительно контролировать то, что пользователи могут и не могут получить доступ на вашем сайте.

Если вы просматриваете демоверсию, доступную с загружаемым исходным кодом, вас встретит индексная страница, которая проверяет ACL для каждого пользователя. Вы можете выбрать разные ссылки внизу, чтобы просмотреть ACL для разных пользователей. Если вы нажмете ссылку «Экран администратора» вверху, вы сможете просмотреть пример интерфейса администратора, который позволяет вам управлять пользователями, ролями и разрешениями. ПРИМЕЧАНИЕ. Администратор будет выполнять восстановление базы данных каждые 30 минут, чтобы убедиться, что все работает. В загружаемых файлах также реализована защита ACL на сайте администратора, поэтому, если у пользователя номер один нет разрешения «доступ администратора», вы не сможете получить доступ к сайту администратора.

Эта система позволит вам создавать различные группы пользователей (например, гости, премиум-участники, участники и администраторы). Мы сможем установить уникальные разрешения для каждой группы, а также для отдельных пользователей. Давайте начнем с настройки нашей базы данных MySQL.


Наш ACL будет храниться в реляционной базе данных с использованием шести таблиц (включая таблицу для пользователей). У вас уже должна быть настроена база данных в вашей хост-среде. Мы создадим следующую структуру таблицы:

Таблицы базы данных

Код для создания базы данных доступен в исходных файлах (install.sql), а также есть другой файл (sampleData.sql), который создаст 4 примера пользователей, а также несколько ролей и разрешений, с которыми вы можете тестировать. Просто откройте файлы в вашем любимом текстовом редакторе и скопируйте / вставьте код в панель SQL в phpMyAdmin.


Нам нужно создать включаемый файл, чтобы мы могли подключиться к нашей базе данных. Создайте файл assets / php / database.php и добавьте в него следующий код (замените значения переменных информацией, соответствующей вашей ситуации с хостингом):

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<?php
session_start();
ob_start();
$hasDB = false;
$server = ‘localhost’;
$user = ‘root’;
$pass = ‘mysql’;
$db = ‘acl_test’;
$link = mysql_connect($server,$user,$pass);
if (!is_resource($link)) {
    $hasDB = false;
    die(«Could not connect to the MySQL server at localhost.»);
} else {
    $hasDB = true;
    mysql_select_db($db);
}
?>

В первой строке кода мы вызываем session_start () ; на самом деле мы не будем использовать переменные сеанса, но они понадобятся вам как часть системы входа пользователя. Затем мы вызываем ob_start () для создания буфера вывода. Как правило, когда PHP генерирует страницу, она отправляется в браузер по мере ее создания. Используя ob_start () , страница и заголовки не отправляются в браузер, пока они не загрузятся полностью, или пока мы не вызовем ob_end_flush () . Буферизируя страницу, мы можем перенаправить с помощью PHP в любой точке страницы, а не просто сверху. После отправки заголовков наш единственный вариант перенаправления — с помощью JavaScript. Предприимчивый хакер может легко отключить JavaScript, а затем увидеть нашу незащищенную страницу во всей красе. Эта строка позволяет нам запретить доступ пользователя в любой точке страницы, если это необходимо.

Строки 4-8 устанавливают наши переменные. $ hasDB — это логическое значение, используемое для определения, подключены ли мы. $ server , $ user , $ pass и $ db являются аргументами соединения для сервера. Линия 9 соединяется с сервером, а строка 10 определяет, было ли соединение успешным. Если это так, мы выбираем базу данных для использования; если это не так, мы отображаем сообщение об ошибке, используя die () .


Этот шаг довольно длинный, так как мы создаем класс ACL, который станет основой нашей системы. Я заранее прошу прощения за длину этого шага.

ACL

Наша система ACL будет объектно-ориентированной, поэтому давайте начнем создавать файл класса. Начнем с добавления определения класса, определений переменных и конструктора в файл /assets/php/class.acl.php:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
class ACL
{
    var $perms = array();
    var $userID = 0;
    var $userRoles = array();
     
    function __constructor($userID = »)
    {
        if ($userID != »)
        {
            $this->userID = floatval($userID);
        } else {
            $this->userID = floatval($_SESSION[‘userID’]);
        }
        $this->userRoles = $this->getUserRoles(‘ids’);
        $this->buildACL();
    }
    function ACL($userID=»)
    {
        $this->__constructor($userID);
    }

После создания определения класса мы создаем три переменные класса для хранения информации, которая будет использоваться при создании ACL.

Функция __constructor () используется для инициализации объекта, когда мы хотим загрузить ACL. Он вызывается автоматически, когда мы вызываем новый ACL (); , Затем передается единственный необязательный аргумент пользователя, для которого загружается ACL. Внутри конструктора мы проверяем, был ли передан идентификатор пользователя. Если идентификатор не был передан, мы предполагаем, что мы загрузим ACL для текущего пользователя, вошедшего в систему; поэтому мы читаем в переменной сеанса для этого. Кроме того, если мы передаем идентификатор пользователя, это позволяет нам читать и редактировать ACL для пользователя, отличного от того, который вошел в систему (полезно для вашей страницы администратора).

После того, как мы прочитали идентификатор пользователя, мы вызываем getUserRoles (), чтобы сгенерировать массив ролей, которым назначен пользователь, и сохранить его в переменной класса $ userRoles . В конце конструктора мы вызываем buildACL () для генерации фактического ACL. Метод с именем ACL () является опорой для установки PHP4. Когда вы вызываете новый ACL () в PHP5, интерпретатор PHP запускает метод __constructor () . Однако когда вы запускаете тот же код в PHP4, интерпретатор запускает ACL () . Предоставляя метод с именем, совпадающим с классом, мы делаем класс PHP4 совместимым.

Каждый раз, когда мы создаем новый объект ACL, передавая идентификатор пользователя, этот объект будет содержать разрешения для пользователя, который был передан.

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
function getUserRoles()
{
    $strSQL = «SELECT * FROM `user_roles` WHERE `userID` = » .
    $data = mysql_query($strSQL);
    $resp = array();
    while($row = mysql_fetch_array($data))
    {
        $resp[] = $row[‘roleID’];
    }
    return $resp;
}
function getAllRoles($format=’ids’)
{
    $format = strtolower($format);
    $strSQL = «SELECT * FROM `roles` ORDER BY `roleName` ASC»;
    $data = mysql_query($strSQL);
    $resp = array();
    while($row = mysql_fetch_array($data))
    {
        if ($format == ‘full’)
        {
            $resp[] = array(«ID» => $row[‘ID’],»Name» => $row[‘roleName’]);
        } else {
            $resp[] = $row[‘ID’];
        }
    }
    return $resp;
}
function buildACL()
{
    //first, get the rules for the user’s role
    if (count($this->userRoles) > 0)
    {
        $this->perms = array_merge($this->perms,$this->getRolePerms($this->userRoles));
    }
    //then, get the individual user permissions
    $this->perms = array_merge($this->perms,$this->getUserPerms($this->userID));
}
function getPermKeyFromID($permID)
{
    $strSQL = «SELECT `permKey` FROM `permissions` WHERE `ID` = » .
    $data = mysql_query($strSQL);
    $row = mysql_fetch_array($data);
    return $row[0];
}
function getPermNameFromID($permID)
{
    $strSQL = «SELECT `permName` FROM `permissions` WHERE `ID` = » .
    $data = mysql_query($strSQL);
    $row = mysql_fetch_array($data);
    return $row[0];
}
function getRoleNameFromID($roleID)
{
    $strSQL = «SELECT `roleName` FROM `roles` WHERE `ID` = » .
    $data = mysql_query($strSQL);
    $row = mysql_fetch_array($data);
    return $row[0];
}
function getUsername($userID)
{
    $strSQL = «SELECT `username` FROM `users` WHERE `ID` = » .
    $data = mysql_query($strSQL);
    $row = mysql_fetch_array($data);
    return $row[0];
}

getUserRoles () вернет массив ролей текущего пользователя, которому он назначен. Сначала мы создадим соответствующий оператор SQL и выполним его. Используя while () , мы перебираем все совпадающие результаты и, наконец, возвращаем массив идентификаторов. Аналогично, getAllRoles () вернет все доступные роли (а не только те, на которые назначен пользователь). Основываясь на значении аргумента $ format , он вернет массив идентификаторов для всех ролей или массив ассоциативного массива с идентификатором и именем каждой роли. Это позволяет нашей функции выполнять двойную функцию. Если мы хотим использовать массив пользовательских ролей в MySQL, нам нужен массив идентификаторов ролей; но если мы хотим отобразить роли на нашей странице, было бы полезно иметь один массив со всей информацией в нем.

buildACL () генерирует массив разрешений для пользователя и является сердцем системы. Сначала мы проверяем, назначен ли пользователь какой-либо роли. Если это так, мы используем array_merge () для объединения существующего массива разрешений с новым массивом, возвращаемым из вызова getRolePerms () (который получает все разрешения для всех ролей, назначенных пользователю). Затем мы делаем то же самое для прав отдельных пользователей, на этот раз вызывая getUserPerms () . Важно, чтобы мы читали пользовательскую perms секунду, потому что array_merge () перезаписывает дубликаты ключей. Секунд чтения полномочий пользователя гарантирует, что отдельные разрешения переопределят любые разрешения, унаследованные от ролей пользователя.

Все функции getPermKeyFromID () , getPermNameFromID () , getRoleNameFromID () и getUsername () являются просто функциями «поиска». Они позволяют нам передавать идентификатор и возвращать соответствующее текстовое значение. Вы можете видеть, что мы строим оператор SQL, затем выполняем его и возвращаем результат. Далее мы добавим две функции, которые будут извлекать разрешения из базы данных.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
function getRolePerms($role)
{
    if (is_array($role))
    {
        $roleSQL = «SELECT * FROM `role_perms` WHERE `roleID` IN (» . implode(«,»,$role) . «) ORDER BY `ID` ASC»;
    } else {
        $roleSQL = «SELECT * FROM `role_perms` WHERE `roleID` = » .
    }
    $data = mysql_query($roleSQL);
    $perms = array();
    while($row = mysql_fetch_assoc($data))
    {
        $pK = strtolower($this->getPermKeyFromID($row[‘permID’]));
        if ($pK == ») { continue;
        if ($row[‘value’] === ‘1’) {
            $hP = true;
        } else {
            $hP = false;
        }
        $perms[$pK] = array(‘perm’ => $pK,’inheritted’ => true,’value’ => $hP,’Name’ => $this->getPermNameFromID($row[‘permID’]),’ID’ => $row[‘permID’]);
    }
    return $perms;
}
 
function getUserPerms($userID)
{
    $strSQL = «SELECT * FROM `user_perms` WHERE `userID` = » .
    $data = mysql_query($strSQL);
    $perms = array();
    while($row = mysql_fetch_assoc($data))
    {
        $pK = strtolower($this->getPermKeyFromID($row[‘permID’]));
        if ($pK == ») { continue;
        if ($row[‘value’] == ‘1’) {
            $hP = true;
        } else {
            $hP = false;
        }
        $perms[$pK] = array(‘perm’ => $pK,’inheritted’ => false,’value’ => $hP,’Name’ => $this->getPermNameFromID($row[‘permID’]),’ID’ => $row[‘permID’]);
    }
    return $perms;
}
function getAllPerms($format=’ids’)
{
    $format = strtolower($format);
    $strSQL = «SELECT * FROM `permissions` ORDER BY `permName` ASC»;
    $data = mysql_query($strSQL);
    $resp = array();
    while($row = mysql_fetch_assoc($data))
    {
        if ($format == ‘full’)
        {
            $resp[$row[‘permKey’]] = array(‘ID’ => $row[‘ID’], ‘Name’ => $row[‘permName’], ‘Key’ => $row[‘permKey’]);
        } else {
            $resp[] = $row[‘ID’];
        }
    }
    return $resp;
}

Эти функции практически идентичны, за исключением таблиц, из которых они извлекаются. Единственный аргумент — это идентификатор ролей / пользователей, которых вы хотите получить. Ролевой функции может быть передан массив или целое число, тогда как пользовательской функции может быть передано только целое число. Используя is_array () , мы определяем, как обрабатывать аргумент для функции разрешения роли. Если это массив, мы используем implode () для создания списка через запятую. В любом случае мы используем это значение в SQL. Затем мы создаем новый пустой массив с именем $ perms — он будет локально хранить разрешения в функции.

Внутри цикла while () мы выполняем несколько функций. Сначала мы генерируем переменную $ pK , которую мы будем использовать в качестве имени ключа массива. Поскольку мы будем искать это значение, чтобы определить, имеет ли пользователь конкретное разрешение, важно, чтобы оно было в едином формате, поэтому мы используем strtolower () . Если значение ключа не указано, мы переходим к следующей итерации, используя continue; , Далее мы смотрим на $ row [‘value’], чтобы установить неявное логическое значение для разрешения. Это гарантирует, что только фактическое значение «1» в таблице будет равно «истина» (т. Е. У пользователя есть разрешение), и это важно для безопасности. В противном случае мы устанавливаем разрешение на false. В конце функции мы создаем массив с несколькими именованными ключами, чтобы мы могли получить всю информацию о разрешении. Этот массив присваивается новому именованному ключу в массиве $ perms, который мы создали ранее. Обратите внимание, что мы используем $ pK для создания индекса с соответствующим именем. Наконец мы возвращаем массив.

Вы можете видеть, что в возвращенном массиве есть индексное имя «унаследовано». Это имеет особое значение для ACL. Если пользователь получает разрешение, потому что он принадлежит роли, которой он назначен, он считается унаследованным. Если разрешения назначаются пользователю вручную, они не наследуются.

В getAllPerms () мы создаем список всех доступных разрешений. Подобно getAllRoles () мы можем передать аргумент формата, чтобы определить, как будут возвращены результаты. Теперь для последней части класса:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    function userHasRole($roleID)
    {
        foreach($this->userRoles as $k => $v)
        {
            if (floatval($v) === floatval($roleID))
            {
                return true;
            }
        }
        return false;
    }
     
    function hasPermission($permKey)
    {
        $permKey = strtolower($permKey);
        if (array_key_exists($permKey,$this->perms))
        {
            if ($this->perms[$permKey][‘value’] === ‘1’ || $this->perms[$permKey][‘value’] === true)
            {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
}
?>

Эти два последних метода очень важны для функциональности ACL. userHasRole () принимает единственный аргумент идентификатора роли. Зацикливаясь на всех элементах массива $ userRoles , мы можем определить, назначен ли пользователь этой роли. Если они есть, мы возвращаем true или false в противном случае. hasPermission () — это метод, который мы используем, чтобы определить, может ли пользователь получить доступ к чему-либо. Мы передаем ключ для разрешения, которое мы хотим проверить. Мы делаем его равномерным, конвертируя его в строчные буквы, и проверяем, есть ли индекс с таким именем в массиве $ perms . Если это так, мы проверяем, что оно установлено в «1», и возвращаем true, или возвращаем false в противном случае. Это функция, которую мы будем использовать, если хотим выяснить, может ли пользователь что-то сделать.


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

Формы пользователя

Откройте /admin/users.php и добавьте следующий код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
<?php
include(«../assets/php/database.php»);
include(«../assets/php/class.acl.php»);
$myACL = new ACL();
if ($myACL->hasPermission(‘access_admin’) != true)<br />{<br /> header(«location: ../index.php»);<br />}
?><!DOCTYPE html PUBLIC «-//W3C//DTD XHTML 1.0 Transitional//EN» «http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd»>
<html xmlns=»http://www.w3.org/1999/xhtml»>
<head>
<meta http-equiv=»Content-Type» content=»text/html; charset=utf-8″ />
<title>ACL Test</title>
<link href=»../assets/css/styles.css» rel=»stylesheet» type=»text/css» />
</head>
<body>
<div id=»header»></div>
<div id=»adminButton»><a href=»../»>Main Screen</a> |
<div id=»page»>
    <!— PAGE CONTENT —>
</div>
</body>
</html>

Как всегда, нам нужно включить нашу базу данных и файлы ACL, а также настроить объект ACL. Затем мы устанавливаем безопасность для страницы. В этом случае мы гарантируем, что у пользователя есть разрешение «access_admin». Если они этого не делают, они перенаправлены.

ПРИМЕЧАНИЕ. Если вы измените разрешения ACL, чтобы у пользователя # 1 больше не было разрешения «access_admin», вы не сможете получить доступ к сайту администратора. Кроме того, вы должны сначала перейти в /index.php, прежде чем перейти на любую из страниц администратора, так как index.php устанавливает переменную сеанса, назначая вам ID пользователя # 1.

Прямо сейчас это только основной макет страницы. На следующих шагах мы заменим <! — PAGE CONTENT -> выше на некоторый код для управления пользователями. Мы будем использовать переменную строки запроса $ action, чтобы определить, какой из пользовательских интерфейсов мы должны отобразить. Есть четыре возможных значения, к которым мы обратимся: если оно пустое, мы отображаем список текущих пользователей. Если установлено значение «пользователь», мы отображаем форму для одного пользователя. Если для него заданы «роли», мы отображаем форму для назначения пользователя. Если для него установлено значение «perms», мы отображаем форму, чтобы предоставить пользователю разрешения.

Добавьте этот код внутри div с идентификатором «page»:

01
02
03
04
05
06
07
08
09
10
<?
    <h2>Select a User to Manage:</h2>
    <?
    $strSQL = «SELECT * FROM `users` ORDER BY `Username` ASC»;
    $data = mysql_query($strSQL);
    while ($row = mysql_fetch_assoc($data))
    {
        echo «<a href=\»?action=user&userID=» . $row[‘ID’] . «\»>» .
    }
} ?>

Концепция здесь довольно проста. Мы строим SQL-запрос, запускаем его и перебираем результаты. Для каждого пользователя мы создаем ссылку, которая позволит нам редактировать этого конкретного пользователя.

Теперь добавьте этот код прямо под предыдущий блок кода:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?
if ($_GET[‘action’] == ‘user’ ) {
    $userACL = new ACL($_GET[‘userID’]);
?>
    <h2>Managing <?= $myACL->getUsername($_GET[‘userID’]);
    … Some form to edit user info …
    <h3>Roles for user: (<a href=»users.php?action=roles&userID=<?= $_GET[‘userID’]; ?>»>Manage Roles</a>)</h3>
    <ul>
    <?
    foreach ($roles as $k => $v)
    {
        echo «<li>» .
    }
    ?>
    </ul>
    <h3>Permissions for user: (<a href=»users.php?action=perms&userID=<?= $_GET[‘userID’]; ?>»>Manage Permissions</a>)</h3>
    <ul>
    <?
    foreach ($perms as $k => $v)
    {
        if ($v[‘value’] === false) { continue;
        echo «<li>» .
        if ($v[‘inheritted’]) { echo » (inheritted)»;
        echo «</li>»;
    }
    ?>
    </ul>
 <?

Когда мы редактируем пользователя, нам нужно загрузить ACL для этого пользователя. Это позволит нам увидеть, какие роли и разрешения у них есть. Мы начинаем это с создания нового объекта ACL и передачи $ userID из строки запроса (таким образом мы загружаем ACL этого пользователя вместо зарегистрированного пользователя). После этого будет отправлена ​​ваша обычная форма редактирования пользователя. Типичными вещами могут быть текстовые поля для редактирования имени пользователя, пароля и т. Д. Ниже мы перечисляем роли, которым назначен пользователь, а также предоставляем ссылку, чтобы мы могли назначить пользователя другим ролям. Строки 10-16 загружают все роли, которые назначены пользователю, и распечатывают их как элементы списка, используя foreach () . Затем мы перечисляем права пользователя аналогичным образом. Мы распечатываем только те разрешения, которые есть у пользователя, а не те, для которых установлено значение false.

Данные пользователя

Наша форма назначения ролей будет выглядеть так:

Роли пользователя

Добавьте этот код прямо под предыдущим блоком кода:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?
 <h2>Manage User Roles: (<?= $myACL->getUsername($_GET[‘userID’]); ?>)</h2>
 <form action=»users.php» method=»post»>
    <table border=»0″ cellpadding=»5″ cellspacing=»0″>
    <tr><th></th><th>Member</th><th>Not Member</th></tr>
    <?
    $roleACL = new ACL($_GET[‘userID’]);
    $roles = $roleACL->getAllRoles(‘full’);
    foreach ($roles as $k => $v)
    {
        echo «<tr><td><label>» .
        echo «<td><input type=\»radio\» name=\»role_» . $v[‘ID’] . «\» id=\»role_» . $v[‘ID’] . «_1\» value=\»1\»»;
        if ($roleACL->userHasRole($v[‘ID’])) { echo » checked=\»checked\»»;
        echo » /></td>»;
        echo «<td><input type=\»radio\» name=\»role_» . $v[‘ID’] . «\» id=\»role_» . $v[‘ID’] . «_0\» value=\»0\»»;
        if (!$roleACL->userHasRole($v[‘ID’])) { echo » checked=\»checked\»»;
        echo » /></td>»;
        echo «</tr>»;
    }
?>
    </table>
    <input type=»hidden» name=»action» value=»saveRoles» />
    <input type=»hidden» name=»userID» value=»<?= $_GET[‘userID’]; ?>» />
    <input type=»submit» name=»Submit» value=»Submit» />
</form>
<form action=»users.php» method=»post»>
    <input type=»button» name=»Cancel» onclick=»window.location=’?action=user&userID=<?= $_GET[‘userID’]; ?>'» value=»Cancel» />
</form>
 <?

Первое, что мы должны сделать здесь, это создать форму и таблицу. Таблица будет иметь 3 столбца: один для роли, один для флажка участника и один для флажка не участника. После создания нового объекта ACL мы загружаем массив всех ролей, используя getAllRoles () . Это позволит нам отображать элементы ввода для каждой роли, а не только для тех, кому назначен пользователь.

Внутри цикла foreach () мы делаем следующее: начинаем новую строку и распечатываем метку с названием роли. Затем мы распечатываем радиокнопку ввода. Имя и идентификатор переключателей делается уникальными для каждой роли с использованием формата «role_ [roleID]» (т.е. role_0012). Строки 13 и 16 определяют, какие из переключателей следует проверять. Первый будет проверен, если пользователь уже назначен в группу, а второй будет проверен, если нет. Обратите внимание, что один имеет значение «1» (для присвоения), а другой — «0» (для «не назначать»). Тогда мы заканчиваем ряд.

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

Форма назначения разрешений аналогична форме ролей, но с другими входными данными, поэтому давайте добавим этот код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?
    <h2>Manage User Permissions: (<?= $myACL->getUsername($_GET[‘userID’]); ?>)</h2>
    <form action=»users.php» method=»post»>
        <table border=»0″ cellpadding=»5″ cellspacing=»0″>
        <tr><th></th><th></th></tr>
        <?
        $userACL = new ACL($_GET[‘userID’]);
        $rPerms = $userACL->perms;
        $aPerms = $userACL->getAllPerms(‘full’);
        foreach ($aPerms as $k => $v)
        {
            echo «<tr><td>» .
            echo «<td><select name=\»perm_» . $v[‘ID’] . «\»>»;
            echo «<option value=\»1\»»;
            if ($rPerms[$v[‘Key’]][‘value’] === true && $rPerms[$v[‘Key’]][‘inheritted’] != true) { echo » selected=\»selected\»»;
            echo «>Allow</option>»;
            echo «<option value=\»0\»»;
            if ($rPerms[$v[‘Key’]][‘value’] === false && $rPerms[$v[‘Key’]][‘inheritted’] != true) { echo » selected=\»selected\»»;
            echo «>Deny</option>»;
            echo «<option value=\»x\»»;
            if ($rPerms[$v[‘Key’]][‘inheritted’] == true || !array_key_exists($v[‘Key’],$rPerms))
            {
                echo » selected=\»selected\»»;
                if ($rPerms[$v[‘Key’]][‘value’] === true )
                {
                    $iVal = ‘(Allow)’;
                } else {
                    $iVal = ‘(Deny)’;
                }
            }
            echo «>Inherit $iVal</option>»;
            echo «</select></td></tr>»;
        }
    ?>
    </table>
    <input type=»hidden» name=»action» value=»savePerms» />
    <input type=»hidden» name=»userID» value=»<?= $_GET[‘userID’]; ?>» />
    <input type=»submit» name=»Submit» value=»Submit» />
<input type=»button» name=»Cancel» onclick=»window.location=’?action=user&userID=<?= $_GET[‘userID’]; ?>'» value=»Cancel» />
</form>
<?

Подобно форме ролей, мы начинаем с добавления формы и таблицы, на этот раз с 2 столбцами. Затем мы создаем объект ACL, извлекаем массив разрешений (строка 8) и получаем массив всех разрешений (строка 9). В цикле foreach () мы выводим новую строку и название разрешения. Затем мы запускаем элемент select. Выбор входа будет иметь 3 варианта: Разрешить, Запретить и Наследовать. Мы смотрим на значение $ rPerms [$ v [‘Key’]] [‘value’], чтобы увидеть, какой вариант следует выбрать. Разрешить или Запретить нельзя, если значение разрешения наследуется благодаря $ rPerms [$ v [‘Key’]] [‘наследуемый’]! = True . Если разрешение наследуется, будет выбран вариант Inherited.

Строки 23-32 улучшают опцию наследования. Если разрешение наследуется, оно делает его выбранным. Затем он определяет значение унаследованного разрешения и устанавливает переменную $ iVal, чтобы мы могли использовать текстовое значение в метке параметра в строке 33. После окончания ввода select и таблицы мы добавляем скрытые входы для настройки сохранения. и добавьте кнопки отправки и отмены.

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

Пользовательские разрешения

Добавьте этот код в /admin/users.php прямо над тегом типа документа:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?
{
    switch($_POST[‘action’])
    {
        case ‘saveRoles’:
            $redir = «?action=user&userID=» .
            foreach ($_POST as $k => $v)
            {
                if (substr($k,0,5) == «role_»)
                {
                    $roleID = str_replace(«role_»,»»,$k);
                    if ($v == ‘0’ || $v == ‘x’) {
                        $strSQL = sprintf(«DELETE FROM `user_roles` WHERE `userID` = %u AND `roleID` = %u»,$_POST[‘userID’],$roleID);
                    } else {
                        $strSQL = sprintf(«REPLACE INTO `user_roles` SET `userID` = %u, `roleID` = %u, `addDate` = ‘%s'»,$_POST[‘userID’],$roleID,date («Ymd H:i:s»));
                    }
                    mysql_query($strSQL);
                }
            }
             
        break;
        case ‘savePerms’:
            $redir = «?action=user&userID=» .
            foreach ($_POST as $k => $v)
            {
                if (substr($k,0,5) == «perm_»)
                {
                    $permID = str_replace(«perm_»,»»,$k);
                    if ($v == ‘x’)
                    {
                        $strSQL = sprintf(«DELETE FROM `user_perms` WHERE `userID` = %u AND `permID` = %u»,$_POST[‘userID’],$permID);
                    } else {
                        $strSQL = sprintf(«REPLACE INTO `user_perms` SET `userID` = %u, `permID` = %u, `value` = %u, `addDate` = ‘%s'»,$_POST[‘userID’],$permID,$v,date («Ymd H:i:s»));
                    }
                    mysql_query($strSQL);
                }
            }
        break;
    }
    header(«location: users.php» . $redir);
}
?>

Этот код сначала проверяет, было ли что-то отправлено, просматривая $ _POST [‘action’] . Это значение, которое было в одном из скрытых элементов формы в двух формах, которые мы создали.

Если мы только что отправили форму ролей, происходит следующее:

  1. Мы строим строку запроса $ redir , куда мы будем отправлены после обработки формы.
  2. Мы перебираем все переменные $ _POST .
  3. Используя substr (), мы выясняем, являются ли первые 5 цифр имени переменной «роль_». Таким образом, мы получаем входные данные только в следующих шагах.
  4. Если значение для текущего ввода равно «0» или «x» (то есть мы не хотим, чтобы у пользователя была эта роль), мы выполняем запрос на удаление. Если мы удалим роль из таблицы user_roles, пользователь больше не будет назначен на роль.
  5. Если значение не равно «0» или «x» (строка 14), мы выполняем запрос замены.
  6. Для любого запроса мы используем sprintf () для обеспечения безопасности ( sprintf () форсирует типизацию переменных и помогает защитить от атак с использованием SQL-инъекций больше информации ).
  7. Мы выполняем SQL с помощью mysql_query () .

Примечание к запросу на замену: Синтаксис замены — это специальный синтаксис MySQL, который позволяет беспрепятственное обновление или вставку Используя замену, это может спасти нас от написания большого количества PHP-кода. Когда мы создали таблицу user_roles, мы создали уникальный индекс для полей userID и roleID. Когда мы выполняем оператор «заменить в», он сначала просматривает таблицу, чтобы увидеть, не создаст ли дубликат вставка новой строки (то есть строка с такими же значениями индекса уже существует). Если есть строка, соответствующая индексам, она обновляет эту строку. Если нет, он вставляет новую строку. Для получения дополнительной информации посетите сайт разработчиков MySQL .

Если мы только что отправили форму с разрешениями, процесс будет таким же, за исключением того, что мы ищем другой префикс для входных имен и используем другую таблицу базы данных. После выполнения каких-либо операций мы используем заголовок («location: …»), чтобы перенаправить обратно на страницу, на которой мы были, и добавляем созданную нами переменную $ redir querystring .


Теперь, когда мы завершили формы для управления нашими пользователями, нам нужно управлять своими ролями. Роли будут более простыми, есть только два действия: просмотреть список ролей или отредактировать роль. Создайте /admin/roles.php со следующим кодом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
<?php
include(«../assets/php/database.php»);
include(«../assets/php/class.acl.php»);
$myACL = new ACL();
if ($myACL->hasPermission(‘access_admin’) != true)<br />{<br /> header(«location: ../index.php»);<br />}
 ?><!DOCTYPE html PUBLIC «-//W3C//DTD XHTML 1.0 Transitional//EN» «http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd»>
<html xmlns=»http://www.w3.org/1999/xhtml»>
<head>
<meta http-equiv=»Content-Type» content=»text/html; charset=utf-8″ />
<title>ACL Test</title>
<link href=»../assets/css/styles.css» rel=»stylesheet» type=»text/css» />
</head>
<body>
<div id=»header»></div>
<div id=»adminButton»><a href=»../»>Main Screen</a> |
<div id=»page»>
    <!— PAGE CONTENT —>
</div>
</body>
</html>

Как и страница пользователей, мы начнем с включений, создания объекта ACL и формата страницы. Наше действие по умолчанию (страница загружена без строки запроса) — перечислить доступные роли, поэтому вставьте этот код вместо <! — PAGE CONTENT ->:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
<?
    <h2>Select a Role to Manage:</h2>
    <?
    $roles = $myACL->getAllRoles(‘full’);
    foreach ($roles as $k => $v)
    {
        echo «<a href=\»?action=role&roleID=» . $v[‘ID’] . «\»>» .
    }
    if (count($roles) < 1)
    {
        echo «No roles yet.<br/ >»;
    } ?>
    <input type=»button» name=»New» value=»New Role» onclick=»window.location=’?action=role'» />
<?

Сначала мы проверяем, была ли строка запроса var пустой. Затем мы сохраняем список всех доступных ролей в $ role с помощью getAllRoles () . На каждой итерации цикла foreach () мы создаем ссылку, которая приведет нас к форме для редактирования отдельной роли. Если в массиве $ role нет ролей, мы выводим дружеское сообщение. Наконец, мы добавляем кнопку, которая позволит нам добавить новую роль.

Добавьте этот код в /admin/roles.php под предыдущим блоком:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?
    if ($_GET[‘roleID’] == ») {
    ?>
    <h2>New Role:</h2>
    <?
    <h2>Manage Role: (<?= $myACL->getRoleNameFromID($_GET[‘roleID’]); ?>)</h2><?
    <form action=»roles.php» method=»post»>
        <label for=»roleName»>Name:</label><input type=»text» name=»roleName» id=»roleName» value=»<?= $myACL->getRoleNameFromID($_GET[‘roleID’]); ?>» />
        <table border=»0″ cellpadding=»5″ cellspacing=»0″>
        <tr><th></th><th>Allow</th><th>Deny</th><th>Ignore</th></tr>
        <?
        $rPerms = $myACL->getRolePerms($_GET[‘roleID’]);
        $aPerms = $myACL->getAllPerms(‘full’);
        foreach ($aPerms as $k => $v)
        {
            echo «<tr><td><label>» .
            echo «<td><input type=\»radio\» name=\»perm_» . $v[‘ID’] . «\» id=\»perm_» . $v[‘ID’] . «_1\» value=\»1\»»;
            if ($rPerms[$v[‘Key’]][‘value’] === true && $_GET[‘roleID’] != ») { echo » checked=\»checked\»»;
            echo » /></td>»;
            echo «<td><input type=\»radio\» name=\»perm_» . $v[‘ID’] . «\» id=\»perm_» . $v[‘ID’] . «_0\» value=\»0\»»;
            if ($rPerms[$v[‘Key’]][‘value’] != true && $_GET[‘roleID’] != ») { echo » checked=\»checked\»»;
            echo » /></td>»;
            echo «<td><input type=\»radio\» name=\»perm_» . $v[‘ID’] . «\» id=\»perm_» . $v[‘ID’] . «_X\» value=\»X\»»;
            if ($_GET[‘roleID’] == » || !array_key_exists($v[‘Key’],$rPerms)) { echo » checked=\»checked\»»;
            echo » /></td>»;
            echo «</tr>»;
        }
    ?>
    </table>
    <input type=»hidden» name=»action» value=»saveRole» />
    <input type=»hidden» name=»roleID» value=»<?= $_GET[‘roleID’]; ?>» />
    <input type=»submit» name=»Submit» value=»Submit» />
</form>
<form action=»roles.php» method=»post»>
    <input type=»hidden» name=»action» value=»delRole» />
    <input type=»hidden» name=»roleID» value=»<?= $_GET[‘roleID’]; ?>» />
    <input type=»submit» name=»Delete» value=»Delete» />
</form>
<form action=»roles.php» method=»post»>
    <input type=»submit» name=»Cancel» value=»Cancel» />
</form>
<?

После проверки, чтобы убедиться, что переменная querystring существует, мы видим, передан ли roleID в строке запроса. Если это так, мы предполагаем, что мы редактируем роль, если не мы ее создаем (мы отображаем соответствующий заголовок). Затем мы создаем форму. Внутри формы нам нужен текстовый ввод для названия нашей роли и таблица для хранения разрешений. В таблице есть столбцы для имени разрешения, разрешить, запретить и игнорировать. Как мы это делали при редактировании разрешений пользователей, мы должны пройти через массив всех разрешений (строка 15, $ myACL-> getAllPerms (‘full’) )

В каждом ряду мы печатаем название разрешения и 3 переключателя. Радиостанции используют ту же номенклатуру, что и пользовательская форма («perm_ [permID]»). «Разрешить» или «Запретить» выбираются в зависимости от значения сохраненного разрешения (благодаря строкам 19 и 22).Если вы выберете «игнорировать», значение для этой роли / разрешения не сохраняется. Обратите внимание, что первые два блока if () содержат && $ _GET [‘roleID’]! = » . Это гарантирует, что если идентификатор пользователя не передается (что мы создаем новую роль), игнорирование выбрано по умолчанию. Затем мы добавляем скрытые данные, чтобы установить параметры сохранения, и закрываем форму. Мы также добавили еще одну форму со скрытыми вводами для удаления роли и другую форму с кнопкой отмены, которая вернет нас на страницу ролей.

Если все идет по плану, мы должны получить следующее при попытке изменить разрешения для роли:

Роль Разрешения

Вставьте этот код в /admin/roles.php прямо перед тегом типа документа:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?
{
    switch($_POST['action'])
    {
        case 'saveRole':
            $strSQL = sprintf("REPLACE INTO `roles` SET `ID` = %u, `roleName` = '%s'",$_POST['roleID'],$_POST['roleName']);
            mysql_query($strSQL);
            if (mysql_affected_rows() > 1)
            {
                $roleID = $_POST['roleID'];
            } else {
                $roleID = mysql_insert_id();
            }
            foreach ($_POST as $k => $v)
            {
                if (substr($k,0,5) == "perm_")
                {
                    $permID = str_replace("perm_","",$k);
                    if ($v == 'X')
                    {
                        $strSQL = sprintf("DELETE FROM `role_perms` WHERE `roleID` = %u AND `permID` = %u",$roleID,$permID);
                        mysql_query($strSQL);
                        continue;
                    }
                    $strSQL = sprintf("REPLACE INTO `role_perms` SET `roleID` = %u, `permID` = %u, `value` = %u, `addDate` = '%s'",$roleID,$permID,$v,date ("Ymd H:i:s"));
                    mysql_query($strSQL);
                }
            }
            header("location: roles.php");
        break;
        case 'delRole':
            $strSQL = sprintf("DELETE FROM `roles` WHERE `ID` = %u LIMIT 1",$_POST['roleID']);
            mysql_query($strSQL);
            $strSQL = sprintf("DELETE FROM `user_roles` WHERE `roleID` = %u",$_POST['roleID']);
            mysql_query($strSQL);
            $strSQL = sprintf("DELETE FROM `role_perms` WHERE `roleID` = %u",$_POST['roleID']);
            mysql_query($strSQL);
            header("location: roles.php");
        break;
    }
}
 
?>

Как и на странице пользователей, мы проверяем, было ли что-то отправлено через $ _POST , и каково значение $ _POST [‘action’] . Если мы сохраняли роль, мы делаем следующее:

  1. Выполните запрос замены в таблице ролей. Это обновит / вставит имя роли. Строки 8-13 выполняют важную функцию сохранения ролей. Если мы выполняем обновление, у нас уже есть идентификатор для роли. Однако, если мы вставляем один, мы не знаем идентификатор роли. Когда мы выполняем запрос на замену, возвращается количество затронутых строк. Если число затронутых строк было больше 1, строка была обновлена, поэтому мы должны использовать идентификатор роли из формы. Если затронутых строк было не больше 1, строка была вставлена, поэтому мы используем mysql_insert_id (), чтобы получить идентификатор для последней вставленной строки.
  2. Затем мы перебираем переменные $ _POST, и строка 16 гарантирует, что мы обрабатываем только те строки, в которых имя ввода начинается с «perm_».
  3. Строка 18 получает floatval () разрешения, поэтому в итоге мы получаем только целочисленный идентификатор perm (поэтому мы знаем, с каким разрешением мы имеем дело).
  4. if ($ v == ‘x’) {…} будет выполняться, если мы выбрали «Игнорировать» для разрешения в форме. Он попытается удалить строку из таблицы, в которой указаны правильный идентификатор строки и идентификатор разрешения. Если это произойдет, мы используем продолжить; перейти к следующей переменной.
  5. Если мы дошли до этого момента, мы предполагаем, что мы хотим добавить или обновить разрешение для этой роли. Таким образом, мы используем синтаксис «заменить в», который мы использовали в пользовательской форме. Важно, чтобы у нас были roleID и permID, чтобы база данных могла проверить существующую строку.
  6. Наконец мы выполняем SQL и перенаправляем на страницу ролей.

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


Как и роли администратора, администратор полномочий будет иметь две функции: список доступных разрешений и разрешения на редактирование. Начните с этого кода в /admin/perms.php:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
<?php
include("../assets/php/database.php");
include("../assets/php/class.acl.php");
$myACL = new ACL();
if ($myACL->hasPermission('access_admin') != true)<br />{<br /> header("location: ../index.php");<br />}
?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns=»http://www.w3.org/1999/xhtml»>
<head>
<meta http-equiv=»Content-Type» content=»text/html; charset=utf-8″ />
<title>ACL Test</title>
<link href="../assets/css/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="header"></div>
<div id="adminButton"><a href="../">Main Screen</a> | <a href="index.php">Admin Home</a></div>
<div id="page">
    <!-- PAGE CONTENT -->
</div>
</body>
</html>

Поместите этот код на страницу div (вместо <! — PAGE CONTENT ->):

01
02
03
04
05
06
07
08
09
10
11
12
13
14
<?
    <h2>Select a Permission to Manage:</h2>
    <?
    $roles = $myACL->getAllPerms('full');
    foreach ($roles as $k => $v)
    {
        echo "<a href=\"?action=perm&permID=" . $v['ID'] . "\">" . $v['Name'] . "</a><br />";
    }
    if (count($roles) < 1)
    {
        echo "No permissions yet.<br />";
    } ?>
    <input type="button" name="New" value="New Permission" onclick="window.location='?action=perm'" />
<?

Сначала мы будем использовать getAllPerms (), чтобы получить массив всех разрешений. Затем мы пройдемся по нему, чтобы построить наш список. Каждая итерация цикла foreach () будет генерировать ссылку, которая будет направлять нас на страницу для редактирования данного разрешения. Если никаких разрешений нет, мы показываем сообщение, говорящее об этом, и заканчиваем форму кнопкой «Новое разрешение». И результат:

Форма разрешений

Чтобы редактировать / добавить индивидуальное разрешение, нам нужно добавить этот код сразу после предыдущего блока:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
<?
    if ($_GET['permID'] == '') {
    ?>
    <h2>New Permission:</h2>
    <?
    } ?>
    <form action="perms.php" method="post">
        <label for="permName">Name:</label><input type="text" name="permName" id="permName" value="<?= $myACL->getPermNameFromID($_GET['permID']); ?>" maxlength="30" /><br />
        <label for="permKey">Key:</label><input type="text" name="permKey" id="permKey" value="<?= $myACL->getPermKeyFromID($_GET['permID']); ?>" maxlength="30" /><br />
    <input type="hidden" name="action" value="savePerm" />
    <input type="hidden" name="permID" value="<?= $_GET['permID']; ?>" />
    <input type="submit" name="Submit" value="Submit" />
</form>
<form action="perms.php" method="post">
     <input type="hidden" name="action" value="delPerm" />
     <input type="hidden" name="permID" value="<?= $_GET['permID']; ?>" />
    <input type="submit" name="Delete" value="Delete" />
</form>
<form action="perms.php" method="post">
    <input type="submit" name="Cancel" value="Cancel" />
</form>
<?

Как и в форме ролей, мы проверяем, предоставлен ли идентификатор разрешения в строке запроса, и отображаем заголовок добавления или обновления на основе этого. Мы открываем тег формы и добавляем два текстовых ввода: один для имени разрешения, другой для ключа разрешения. Имя — это то, что будет отображаться в формах, а ключ — то, что мы будем использовать в сценариях. Ключ должен быть почти таким же, как и имя, за исключением того, что он не должен содержать пробелов или символов и должен быть в нижнем регистре. Для обоих текстовых полей мы предоставляем значения по умолчанию, если мы обновляем.

В конце формы мы добавляем скрытые данные и кнопку отправки. Тогда у нас есть формы удаления и отмены.

Наконец, нам нужно сохранить форму разрешения, поэтому добавьте этот код в начало /admin/perms.php прямо над типом документа.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
if (isset($_POST['action']))
{
    switch($_POST['action'])
    {
        case 'savePerm':
            $strSQL = sprintf("REPLACE INTO `permissions` SET `ID` = %u, `permName` = '%s', `permKey` = '%s'",$_POST['permID'],$_POST['permName'],$_POST['permKey']);
            mysql_query($strSQL);
        break;
        case 'delPerm':
            $strSQL = sprintf("DELETE FROM `permissions` WHERE `ID` = %u LIMIT 1",$_POST['permID']);
            mysql_query($strSQL);
        break;
    }
    header("location: perms.php");
}

Как и все остальные сценарии отправки, нам нужно выяснить, какое действие было отправлено. Если мы сохраняем разрешение, мы выполняем замену в операции. Это будет либо обновлять, либо вставлять по мере необходимости. Если мы отправили форму удаления, мы выполняем запрос на удаление. В любом случае мы будем перенаправлены на perms.php.


Нам нужна отправная точка для нашего администратора ACL. Мы просто создадим что-то простое со ссылками на 3 страницы. Вот предварительный просмотр и код для него:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
include("../assets/php/database.php");
include("../assets/php/class.acl.php");
$myACL = new ACL();
if ($myACL->hasPermission('access_admin') != true)<br />{<br /> header("location: ../index.php");<br />}
?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns=»http://www.w3.org/1999/xhtml»>
<head>
<meta http-equiv=»Content-Type» content=»text/html; charset=utf-8″ />
<title>ACL Test</title>
<link href="../assets/css/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="header"></div>
<div id="adminButton"><a href="../">Main Screen</a></div>
<div id="page">
    <h2>Select an Admin Function:</h2>
    <a href="users.php">Manage Users</a><br />
    <a href="roles.php">Manage Roles</a><br />
    <a href="perms.php">Manage Permissions</a><br />
</div>
</body>
</html>

Довольно понятно, у нас есть 3 ссылки для управления 3 различными аспектами вашего ACL.


Показатель

Внедрить вашу новую систему ACL на вашем сайте довольно легко. Каждая страница, которую вы хотите защитить, должна иметь базу данных и ACL-файл, включенный в верхней части. После этого вы должны создать новый экземпляр объекта ACL.

В качестве примера, скажем, вы установили разрешение с помощью ключа «access_admin» и хотели использовать его для управления доступом к интерфейсу администратора. В верхней части вашей страницы вы можете использовать этот скрипт, чтобы проверить его:

1
2
3
4
5
6
7
8
9
<?php
include("assets/php/database.php");
include("assets/php/class.acl.php");
$myACL = new ACL();
if ($myACL->hasPermission('access_admin') != true)
{
    header("location: insufficientPermission.php");
}
?>

Как видите, мы создаем объект ACL. Поскольку мы не передаем идентификатор пользователя в качестве аргумента, система прочитает переменную сеанса $ _SESSION [‘userID’] . Затем мы используем $ myACL-> hasPermission (‘access_admin’), чтобы проверить, есть ли у пользователя такое разрешение. Если они этого не делают, они перенаправляются на достаточное количество файлов. Таким образом, они не могут попасть в безопасные зоны, для которых у них нет разрешений.

В предоставленных исходных файлах я предоставил индексный файл, который предоставляет простой тест ACL на основе приведенного выше примера кода. Пример индекса отображает список всех разрешений и значки, показывающие, может ли текущий пользователь получить доступ к каждому из них. Существует также список пользователей, который позволяет вам изменить пользователя, для которого отображается ACL. Вот код для примера индекса:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?php
include("assets/php/database.php");
include("assets/php/class.acl.php");
 
$userID = $_GET['userID'];
$_SESSION['userID'] = 1;
$myACL = new ACL();
?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns=»http://www.w3.org/1999/xhtml»>
<head>
<meta http-equiv=»Content-Type» content=»text/html; charset=utf-8″ />
<title>ACL Test</title>
<link href="assets/css/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="header"></div>
<div id="adminButton"><a href="admin/">Admin Screen</a></div>
<div id="page">
    <h2>Permissions for <?= $myACL->getUsername($userID); ?>:</h2>
    <?
        $userACL = new ACL($userID);
        $aPerms = $userACL->getAllPerms('full');
        foreach ($aPerms as $k => $v)
        {
            echo "<strong>" . $v['Name'] . ": </strong>";
            echo "<img src=\"assets/img/";
            if ($userACL->hasPermission($v['Key']) === true)
            {
                echo "allow.png";
                $pVal = "Allow";
            } else {
                echo "deny.png";
                $pVal = "Deny";
            }
            echo "\" width=\"16\" height=\"16\" alt=\"$pVal\" /><br />";
        }
    ?>
    <h3>Change User:</h3>
    <?
        $strSQL = "SELECT * FROM `users` ORDER BY `Username` ASC";
        $data = mysql_query($strSQL);
        while ($row = mysql_fetch_assoc($data))
        {
            echo "<a href=\"?userID=" . $row['ID'] . "\">" . $row['username'] . "</a><br />";
        }
    ?>
</div>
</body>
</html>

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