Глава 4. Система пользователей и разграничение прав (ACL)

07-07-26 10:18

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


4.1. Группы пользователей и системные роли

Система управления доступом в Seditio построена на ролевой модели. Все зарегистрированные пользователи обязательно состоят в группах.

4.1.1. Системные (зарезервированные) группы пользователей

В Seditio по умолчанию присутствуют предопределенные группы с зарезервированными идентификаторами (ID), которые жестко завязаны на внутреннюю логику ядра:

  1. Guests (Гости / ID = 1): Неавторизованные посетители сайта. Группа определяет, к какому контенту и функционалу сайта есть публичный доступ.
  2. Inactive (Неактивные / ID = 2): Пользователи, прошедшие регистрацию, но ожидающие активации аккаунта (например, по ссылке из e-mail или после проверки администратором).
  3. Banned (Заблокированные / ID = 3): Пользователи, аккаунты которых временно или навсегда заблокированы.
  4. Members (Участники / ID = 4): Стандартная группа для всех успешно зарегистрированных и активированных пользователей сайта.
  5. Team members (Администраторы / ID = 5): Члены команды с полными административными правами. Пользователи этой группы имеют доступ в панель управления (/admin или index.php?module=admin без ЧПУ) по умолчанию.
  6. Moderators (Модераторы / ID = 6): Группа пользователей с модераторскими привилегиями на форумах и в категориях страниц.

4.1.2. Концепция основной группы и дополнительных групп

У каждого пользователя в Seditio есть две плоскости принадлежности к группам:

  • Основная группа (user_maingrp): Хранится в таблице пользователей sed_users. Она определяет базовую роль пользователя на сайте, его скин по умолчанию, язык интерфейса и уровень доступа.
  • Дополнительные группы (Таблица sed_groups_users): Пользователь может состоять в неограниченном числе дополнительных групп. Принадлежность связывается через таблицу отношений sed_groups_users (колонки gru_userid и gru_groupid).

При проверке прав доступа ядро Seditio объединяет привилегии основной группы пользователя и всех дополнительных групп, в которых он состоит.


4.2. Архитектура и битовая маска ACL (Access Control List)

Вся матрица прав доступа в Seditio CMS хранится в таблице sed_auth. Запись о правах привязывается к группе пользователей (auth_groupid), области системы (auth_code — например, page, forums, admin) и конкретной опции внутри этой области (auth_option — например, категория страниц или раздел форума).

4.2.1. Байт как битовая маска прав доступа

Для минимизации размера базы данных и максимальной производительности права на конкретное действие хранятся в виде 8-битного целого числа (один байт от 0 до 255), где каждый бит отвечает за определенное разрешение:

  • Бит 0 (вес 1): Read (Чтение / R). Разрешает просмотр контента.
  • Бит 1 (вес 2): Write (Запись / W). Разрешает добавление и редактирование собственного контента.
  • Бит 2 (вес 4): Пользовательское разрешение 1 (1).
  • Бит 3 (вес 8): Пользовательское разрешение 2 (2).
  • Бит 4 (вес 16): Пользовательское разрешение 3 (3).
  • Бит 5 (вес 32): Пользовательское разрешение 4 (4).
  • Бит 6 (вес 64): Пользовательское разрешение 5 (5).
  • Бит 7 (вес 128): Admin (Администрирование / A). Разрешает модерирование, удаление чужого контента и управление настройками раздела.

Таким образом, если группа имеет полные права на раздел (Чтение + Запись + Администрирование), значение её прав в БД будет равно 1 + 2 + 128 = 131.


4.2.2. Наследование и кумулятивное сложение прав

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

При авторизации пользователя функция sed_auth_build() запрашивает права для всех групп, в которых состоит пользователь, и собирает их в единую сетку прав с использованием побитового оператора ИЛИ (|=):

// Cumulative bitwise OR merging of user rights from multiple groups
@$authgrid[$row['auth_code']][$row['auth_option']] |= $row['auth_rights'];

Пример:

  • Пользователь состоит в группе Members, у которой права на чтение форума равны 1 (только Чтение).
  • Этот же пользователь состоит в дополнительной группе Moderators, у которой права на этот же форум равны 128 (Администрирование).
  • Итоговые права пользователя составят 1 | 128 = 129 (Чтение + Администрирование).

4.3. Процесс проверки авторизации в коде (sed_auth)

Ядро системы использует встроенные функции для построения и проверки сетки прав.

4.3.1. Сборка сетки прав при входе пользователя

При успешной авторизации или при первом обращении к странице вызывается функция sed_auth_build(). Она сканирует все группы пользователя, выполняет SQL-запрос к таблице sed_auth и строит двумерный ассоциативный массив вида:

$usr['auth'][$area][$option] = $bitwise_rights;

4.3.2. Проверка доступа в коде

Для проверки наличия прав в PHP-скриптах используется ключевая функция sed_auth(). Она принимает три параметра:

  • $area (string) — защищаемая область (например, 'page', 'forums', 'admin').
  • $option (string) — конкретный подраздел или категория (например, 'news' для категории страниц).
  • $mask (string) — строка проверяемых масок (по умолчанию 'RWA').

Функция сопоставляет битовую маску запрашиваемых прав с правами текущего пользователя и возвращает TRUE или FALSE.

Пример проверки прав в коде:

// Check if user has both Read ® and Write (W) permissions for 'page' module, category 'news'
list($usr['auth_read'], $usr['auth_write'], $usr['isadmin']) = sed_auth('page', 'news', 'RWA');

if (!$usr['auth_read']) {
    // Redirect or show error if no read rights
    sed_die();
}

4.3.3. Оптимизация производительности: кэширование прав

Для того чтобы избежать выполнения ресурсоемких SQL-запросов и побитового объединения массивов прав при каждом клике пользователя, Seditio CMS кэширует готовую сетку прав авторизованного пользователя:

  • В таблице sed_users предусмотрено поле user_auth типа TEXT.
  • При первой сборке прав результат работы sed_auth_build() сериализуется через serialize() и сохраняется в это поле.
  • При каждом последующем обращении к страницам права пользователя мгновенно загружаются из базы данных одной строкой и десериализуются: $usr['auth'] = unserialize($row['user_auth']);.
  • Сброс кэша: При изменении прав групп в админке или добавлении пользователей в новые группы система принудительно сбрасывает кэш прав всех пользователей (UPDATE sed_users SET user_auth=''), что заставит ядро перегенерировать сетку прав при их следующем заходе на сайт.

4.4. Профиль пользователя и механизм его расширения

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

4.4.1. Системная структура профиля

В состав профиля по умолчанию входят следующие ключевые поля:

  • user_id — уникальный идентификатор пользователя.
  • user_name — логин (уникальное имя для авторизации).
  • user_password и user_salt — хэш пароля и соль.
  • user_maingrp — основная группа пользователя.
  • user_email — адрес электронной почты.
  • user_avatar и user_photo — аватар и фотография.
  • user_timezone, user_lang, user_skin — региональные настройки (часовой пояс, язык, тема оформления).
  • user_regdate, user_lastlog, user_lastip — статистика активности.

4.4.2. Расширение профиля с помощью словарей

Если стандартных полей профиля недостаточно (например, требуется добавить поля «Номер телефона», «Адрес доставки» или «Telegram ID»), администратор может расширить профиль без изменения исходного PHP-кода:

  1. В разделе «Словари» по адресу /admin/dic (или index.php?module=admin&m=dic без ЧПУ) создается новый словарь.
  2. Целевой таблицей выбирается таблица пользователей users.
  3. Создаются элементы словаря (sed_dic / sed_dic_items).
  4. Система выполняет SQL-запрос ALTER TABLE sed_users ADD user_field_name ..., физически расширяя структуру базы данных.
  5. Новое поле автоматически интегрируется в форму редактирования профиля в кабинете пользователя, в панель администрирования и становится доступно в TPL-шаблонах через теги вида {USER_FIELD_NAME}.

4.5. Механизм сессий, авторизации и безопасности

Безопасность авторизации пользователей обеспечивается комплексом мер на уровне сессий, кук и криптографического хэширования.

4.5.1. Схема авторизации и Persistent Login

В Seditio поддерживается три режима авторизации (задаются через конфигурацию $cfg['authmode']):

  1. Только сессии (режим 1): Авторизация привязана к сессии PHP.
  2. Только куки (режим 2): Персистентный вход.
  3. Смешанный режим (режим 3): Используются и куки, и сессии.

При персистентном входе авторизация базируется на специальной куке автологина с именем $sys['site_id']:

  • Данные в куке хранятся в зашифрованном base64 виде и имеют структуру: user_id:_:user_secret:_:user_skin.
  • При каждом запросе ядро считывает куку, декодирует её и сопоставляет поля с базой данных:
    // Decoding persistent login cookie value
    $u = base64_decode($_COOKIE[$sys['site_id']]);
    $u = explode(':_:', $u);
    $rsedition = $u[0]; // User ID
    $rseditiop = $u[1]; // User Secret hash
    
  • Если включена проверка по IP ($cfg['ipcheck']), ядро дополнительно проверяет совпадение текущего IP-адреса пользователя с IP-адресом его последнего входа (user_lastip), что защищает от перехвата сессии/куки.

4.5.2. Хэширование паролей и использование Site Secret

Для защиты паролей от компрометации в случае утечки базы данных в Seditio используется двухфакторное хэширование с солью:

  • При регистрации для пользователя генерируется уникальная случайная соль (user_salt).
  • Хэш пароля генерируется функцией sed_hash() с использованием глобального секретного ключа сайта $cfg['site_secret'] (задается в файле datas/config.php при установке):
    // Hashing logic using user salt and unique site secret key
    $res = hash($algorithm, hash($algorithm, $password) . $cfg['site_secret'] . $salt);
    
  • Двойное обертывание алгоритмом хэширования (md5 по умолчанию) и уникальная соль для каждого пользователя защищают пароли от взлома по радужным таблицам (Rainbow Tables).

4.5.3. Защита от брутфорса и Бан-лист

  • Аудит неудачных попыток входа: В системе ведется журнал логирования. Все неудачные попытки авторизации под любым именем записываются в лог безопасности (sec), включая IP-адрес нападающего.
  • Блокировки по IP и e-mail (Бан-лист): В панели управления по адресу /admin/banlist (или index.php?module=admin&m=banlist без ЧПУ) администратор может блокировать доступ к сайту по конкретному IP, маске подсети (например, 192.168.1.*) или по e-mail маске (например, *@spamdomain.com). При обращении к любой странице ядро Seditio сверяет IP посетителя с бан-листом и при совпадении немедленно прекращает выполнение скрипта.

Оценка:
(0.00)

Пока комментариев нет