PHP

Контроль доступа с использованием битовой маски

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

Примечание: для использования системы контроля прав доступа следует ознакомиться (или вспомнить) с побитовыми операторами PHP.

Шаг 1. HTML
Наш демонстрационный проект содержит 3 HTML файла с шаблонами:

main_page.html
<!DOCTYPE html>
<html lang="ru" >
<head>
    <title>Контроль доступа с использованием битовой маски</title>
    <meta charset="utf-8">
    <link href="css/main.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <header>
        <h2>Контроль доступа с использованием битовой маски</h2>
        <a href="http://www.ruseller.com/" class="stuts">Материалы сайта <span>RUSELLER.COM</span></a>
    </header>
    <div class="container">
        {form}
    </div>
</body>
</html>

Очень простой шаблон.

login_form.html
<div class="column">
    <h3>Демонстрация системы контроля доступа</h3>
    <p>вы можете использовать следующие имена пользователей "User", "Writer", "Moderator" и "Admin" с паролем "password" для входа в систему. Каждый пользователь имеет свой набор прав доступа к информации.</p>
</div>
<div class="column">
    <form class="login_form" action="index.php" method="post">
        <h3>Войти</h3>
        <label>Имя пользователя:</label><input type="text" name="username">
        <label>Пароль:</label><input type="password" name="password">
        <input type="submit" name="LogIn" value="Войти">
    </form>
</div>

Форма входа в систему.

logout_form.html
<div class="column">
    <h3>Здравствуйте, {name}</h3>
    <h3>Ваша битовая маска:</h3>
    <div>{bit_mask}</div>
    <h3>Ваши возможности:</h3>
    <div>{possibilities}</div>
</div>
<div class="column">
    <a href="index.php?logout">Выйти</a>
</div>

Шаблон, который предоставляет возможности выхода из системы.

Шаг 2. CSS
css/main.css
В файле содержится несколько стилей для формирования внешнего вида страниц демонстрационного проекта. Код можно найти в исходниках.

Шаг 3. PHP
А теперь рассмотрим основной функционал нашего маленького проекта:

index.php
<?php
 
// Определяем битоовую маску для прав доступа
define('CAN_READ', 1 << 0);   // 000001
define('CAN_CREATE', 1 << 1); // 000010
define('CAN_EDIT_OWN', 1 << 2);   // 000100
define('CAN_DELETE_OWN', 1 << 3); // 001000
define('CAN_EDIT_ANY', 1 << 4);   // 010000
define('CAN_DELETE_ANY', 1 << 5); // 100000
 
//  Инициализация системы логина и генерирование кода
$oSimpleAccessSystem = new SimpleAccessSystem();
$sLoginForm = $oSimpleAccessSystem->getLoginBox();
echo strtr(file_get_contents('main_page.html'), array('{form}' => $sLoginForm));
 
// класс SimpleAccessSystem
class SimpleAccessSystem {
 
    // Переменные
    var $aMembers; // Массив пользователей
 
    // Конструктор
    function SimpleAccessSystem() {
        session_start();
 
        // Разные набор прав доступа
        $sUserPerm = CAN_READ;
        $sWriterPerm = CAN_READ | CAN_CREATE | CAN_EDIT_OWN | CAN_DELETE_OWN;
        $sModeratorPerm = CAN_READ | CAN_EDIT_ANY | CAN_DELETE_ANY;
        $sAdminPerm = CAN_READ | CAN_CREATE | CAN_EDIT_OWN | CAN_DELETE_OWN | CAN_EDIT_ANY | CAN_DELETE_ANY;
 
        /* hash = sha1(md5('password') . 'testing'); */
        $this->aMembers = array(
            'User' => array('hash' => 'b88c654d6c68fc37f4dda1d29935235eea9a845b', 'salt' => 'testing', 'rule' => $sUserPerm),
            'Writer' => array('hash' => 'b88c654d6c68fc37f4dda1d29935235eea9a845b', 'salt' => 'testing', 'rule' => $sWriterPerm),
            'Moderator' => array('hash' => 'b88c654d6c68fc37f4dda1d29935235eea9a845b', 'salt' => 'testing', 'rule' => $sModeratorPerm),
            'Admin' => array('hash' => 'b88c654d6c68fc37f4dda1d29935235eea9a845b', 'salt' => 'testing', 'rule' => $sAdminPerm)
        );
    }
 
    // Функция входа в систему
    function getLoginBox() {
        if (isset($_GET['logout'])) { // Осуществляется выход
            if (isset($_SESSION['member_name']) && isset($_SESSION['member_pass']))
                $this->performLogout();
        }
 
        if ($_POST && $_POST['username'] && $_POST['password']) { // Осуществляется вход в систему
            if ($this->checkLogin($_POST['username'], $_POST['password'], false)) { // Успешный вход
                $this->performLogin($_POST['username'], $_POST['password']);
                header( "Location:{$_SERVER['REQUEST_URI']}" );
                exit;
            } else { // Неправильное имя пользователя
                ob_start(); // получаем шаблон формы входа
                require_once('login_form.html');
                $sLoginForm = ob_get_clean();
                return $sLoginForm . '<h2>Имя пользователя или пароль неправильные</h2>';
            }
        } else { // в случае, если пользователь уже вошел в систему (на обновленной странице):
            if (isset($_SESSION['member_name']) && $_SESSION['member_name'] && $_SESSION['member_pass']) {
                if ($this->checkLogin($_SESSION['member_name'], $_SESSION['member_pass'])) {
                    $sRule = $this->aMembers[$_SESSION['member_name']]['rule'];
                    $sPermissions = '';
                    $sPermissions .= $this->isCanRead($sRule);
                    $sPermissions .= $this->isCanCreate($sRule);
                    $sPermissions .= $this->isCanEdit($sRule);
                    $sPermissions .= $this->isCanEditAny($sRule);
                    $sPermissions .= $this->isCanDelete($sRule);
                    $sPermissions .= $this->isCanDeleteAny($sRule);
 
                    ob_start(); // Получаем шаблон формы выхода
                    require_once('logout_form.html');
                    $sLogoutForm = ob_get_clean();
                    $sLogoutForm = str_replace('{name}', $_SESSION['member_name'], $sLogoutForm);
                    $sLogoutForm = str_replace('{bit_mask}', $sRule, $sLogoutForm);
                    $sLogoutForm = str_replace('{possibilities}', $sPermissions, $sLogoutForm);
                    return $sLogoutForm;
                }
            }
 
            // Иначе - выводим форму входа
            ob_start();
            require_once('login_form.html');
            $sLoginForm = ob_get_clean();
            return $sLoginForm;
        }
    }
 
    // Функции проверки
    function isCanRead($sRule) {
        return ($sRule & CAN_READ) ? 'Вы имеете права на чтение информации<br />' : '';
    }
    function isCanCreate($sRule) {
        return ($sRule & CAN_CREATE) ? 'Вы имеете права на создание информации<br />' : '';
    }
    function isCanEdit($sRule) {
        return ($sRule & CAN_EDIT_OWN) ? 'Вы можете редактировать только вашу информацию<br />' : '';
    }
    function isCanEditAny($sRule) {
        return ($sRule & CAN_EDIT_ANY) ? 'Вы можете редактировать любую информацию<br />' : '';
    }
    function isCanDelete($sRule) {
        return ($sRule & CAN_DELETE_OWN) ? 'Вы можете удалять только вашу информацию<br />' : '';
    }
    function isCanDeleteAny($sRule) {
        return ($sRule & CAN_DELETE_ANY) ? 'Вы можете удалять любую информацию<br />' : '';
    }
 
    // Выполняем вход
    function performLogin($sName, $sPass) {
        $this->performLogout();
 
        $sSalt = $this->aMembers[$sName]['salt'];
        $sPass = sha1(md5($sPass) . $sSalt);
 
        $_SESSION['member_name'] = $sName;
        $_SESSION['member_pass'] = $sPass;
    }
 
    // Выполняем выход
    function performLogout() {
        unset($_SESSION['member_name']);
        unset($_SESSION['member_pass']);
    }
 
    // Проверка входа
    function checkLogin($sName, $sPass, $isHash = true) {
        if (isset($this->aMembers[$sName])) {
            if (! $isHash) {
                $sSalt = $this->aMembers[$sName]['salt'];
                $sPass = sha1(md5($sPass) . $sSalt);
            }
            return ($sPass == $this->aMembers[$sName]['hash']);
        }
        return false;
    }
}

Сначала определяем константы для прав доступа (битовую маску). Затем перечисляются пользователи системы, для которых устанавливаются разные права доступа (с помощью логического оператора ИЛИ |). В демонстрации для хранения информации о пользователях используется массив, но в реальном проекте лучше всего задействовать базу данных. В нашем проекте используются функции проверки прав доступа, которые помогают определять доступность действий для пользователя.

В такой функции используются логический оператор И &. В демонстрации проверяется один бит в каждой функции. Если вы захотите осуществлять комплексную проверку, то надо воспользоваться другими логическими операторами. Например, вот так будет выглядеть функция для проверки прав пользователя на чтение и запись одновременно.:
function isCanReadCreate($sRule) {
    return ($sRule & (CAN_READ | CAN_CREATE));
}

Данная функция возвращает True или False.
Теги:
Контроль доступа
Добавлено: 02 Мая 2018 20:12:39 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...