Как настроить RLS (ограничение доступа) по реквизиту пользователя для регистра сведений?

Программист 1С v8.3 (Управляемые формы) Управленческий учет IT и автоматизация бизнеса
← На главную

При разработке систем учета часто возникает задача разграничения прав доступа к чувствительным данным, например, к информации о заработной плате или ФОТ (Фонде оплаты труда). Рассмотрим ситуацию, когда у нас есть Регистр сведений с данными о зарплате, и нам необходимо сделать так, чтобы каждый сотрудник видел только свои данные. При этом связь "Пользователь базы — Сотрудник" хранится в реквизитах справочника пользователей.

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

Постановка задачи

Иногда требуется не только ограничить записи, но и обеспечить доступ и видимость реквизитов документов. Имеется регистр сведений (РС), содержащий измерение Сотрудник и ресурс ФОТ. Требуется настроить права доступа так, чтобы пользователь, заходя в систему, видел записи в этом регистре только по тому сотруднику, который сопоставлен с его учетной записью.

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

Принцип аддитивности прав доступа

Прежде чем писать код RLS, необходимо разобраться с фундаментом системы прав доступа 1С. Важнейший момент, который часто упускают новички, заключается в том, что права в 1С работают по принципу сложения (аддитивности).

Что это значит?

Если пользователю назначены две роли:

  1. Роль А: Имеет RLS, который разрешает видеть только "свои" данные.
  2. Роль Б: (например, типовая роль "Чтение базовой НСИ" или какая-то старая роль) Разрешает чтение этого регистра без ограничений (быстро найти такие роли поможет Просмотр ролей для объекта (есть готовый отчет для анализа прав доступа и ролей)).
В результате пользователь увидит все данные. "Разрешающая" роль всегда побеждает ограничивающую. RLS работает только тогда, когда во всех ролях, дающих доступ к объекту, прописаны ограничения (либо ограничения прописаны в одной, а остальные роли не дают доступа к этому объекту вовсе).

Поэтому, если вы работаете в типовой конфигурации (ЗУП, ERP, УТ) или в самописной с использованием БСП, первым делом нужно убедиться, что у пользователя нет других ролей, предоставляющих безусловный доступ к нашему регистру сведений. Скорее всего, вам придется создать собственную роль "Чтение ФОТ" и не давать пользователю типовые роли, открывающие этот регистр. Для такой проверки подойдёт инструмент анализа прав доступа по ключевым разрезам.

Выбор архитектурного решения RLS

Теперь перейдем к технической реализации. Автор идеи предлагал написать в шаблоне ограничения доступа что-то вроде:


ГДЕ Сотрудник = &ТекущийПользователь.Сотрудник

Давайте разберем, почему так делать не рекомендуется.

Использование обращения через точку (разыменование ссылочных типов) в тексте запроса RLS приводит к серьезным проблемам с производительностью:

  1. При каждом обращении к регистру система будет выполнять неявное левое соединение (Left Join) с таблицей пользователей.
  2. Если таблица пользователей большая, или если к ней тоже применяется сложный RLS, это может замедлить работу всей базы.
  3. Возможна ошибка рекурсии, если доступ к справочнику пользователей также ограничен через RLS, который зависит от текущего пользователя.

Правильный подход: Параметры сеанса

Для быстрой и корректной работы RLS используются Параметры сеанса. Это значения, которые вычисляются один раз при входе пользователя в систему (или при первом обращении) и хранятся в памяти сервера. Доступ к ним из RLS происходит мгновенно.

Давайте реализуем правильную схему по шагам.

Шаг 1. Создание параметров сеанса

В дереве конфигурации создадим новый параметр сеанса. Назовем его, например, ТекущийСотрудник. Тип данных должен совпадать с типом измерения вашего регистра (СправочникСсылка.Сотрудники или СправочникСсылка.ФизическиеЛица).

Также полезно создать булевый параметр, например ТекущийПользовательВидитВсе, чтобы администраторы и расчетчики могли видеть все данные без ограничений.

Шаг 2. Инициализация параметров

Нам нужно заполнить эти параметры при старте работы пользователя. Для этого используем модуль сеанса.

Откроем модуль сеанса и найдем (или создадим) процедуру УстановкаПараметровСеанса.


Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
    
    // Проверяем, нужно ли инициализировать наш параметр
    Если ТребуемыеПараметры = Неопределено 
       Или ТребуемыеПараметры.Найти("ТекущийСотрудник") <> Неопределено Тогда
        
        // Получаем текущего пользователя
        ТекущийПользовательСсылка = Пользователи.ТекущийПользователь();
        
        // Получаем сотрудника из реквизита пользователя
        // Предположим, у вас есть реквизит "Сотрудник" в справочнике Пользователи
        Запрос = Новый Запрос;
        Запрос.Текст = 
            "ВЫБРАТЬ
            |   Пользователи.Сотрудник КАК Сотрудник,
            |   Пользователи.Администратор КАК Администратор
            |ИЗ
            |   Справочник.Пользователи КАК Пользователи
            |ГДЕ
            |   Пользователи.Ссылка = &Ссылка";
            
        Запрос.УстановитьПараметр("Ссылка", ТекущийПользовательСсылка);
        Выборка = Запрос.Выполнить().Выбрать();
        
        Если Выборка.Следующий() Тогда
            ПараметрыСеанса.ТекущийСотрудник = Выборка.Сотрудник;
            // Логика для полных прав
            ПараметрыСеанса.ТекущийПользовательВидитВсе = Выборка.Администратор; 
        Иначе
            // Если пользователь не найден или реквизит пуст, записываем пустую ссылку
            ПараметрыСеанса.ТекущийСотрудник = Справочники.Сотрудники.ПустаяСсылка();
            ПараметрыСеанса.ТекущийПользовательВидитВсе = Ложь;
        КонецЕсли;
        
    КонецЕсли;

КонецПроцедуры

Шаг 3. Настройка роли и RLS

Теперь перейдем к созданию ограничения.

  1. Создайте новую Роль (например, ЧтениеСвоегоФОТ).
  2. Найдите в списке прав ваш регистр сведений.
  3. Установите право Чтение.
  4. В колонке "Ограничение доступа" для поля "Чтение" откройте редактор ограничения.

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


// Текст ограничения доступа
ГДЕ Сотрудник = &ТекущийСотрудник
ИЛИ &ТекущийПользовательВидитВсе = ИСТИНА

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

Особенности работы с NULL и пустыми значениями

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

В нашем коде инициализации мы присвоили параметру ПараметрыСеанса.ТекущийСотрудник пустую ссылку. В этом случае запрос RLS превратится в ГДЕ Сотрудник = ЗНАЧЕНИЕ(Справочник.Сотрудники.ПустаяСсылка). Пользователь увидит только записи, где измерение Сотрудник не заполнено (если такие есть), или не увидит ничего. Это ожидаемое и безопасное поведение.

Использование шаблонов (Templates)

Если в конфигурации используется Библиотека Стандартных Подсистем (БСП), то часто применяются шаблоны ограничений доступа. Это позволяет не писать код каждый раз заново.

Если вы хотите использовать стандартный механизм БСП "По значениям", то настройка будет выглядеть иначе и требовать создания Групп доступа, Профилей и настройки видов доступа. Однако, автор вопроса хотел избежать создания отдельных Групп доступа для каждого пользователя.

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

На вкладке Шаблоны в роли создадим шаблон #ПоСвоемуСотруднику с текстом:


ГДЕ Сотрудник = &ТекущийСотрудник 
ИЛИ &ТекущийПользовательВидитВсе = ИСТИНА

Тогда в поле ограничения доступа самого регистра достаточно написать только имя шаблона:


#ПоСвоемуСотруднику

Как это повлияет на отчеты и списки?

После применения такой настройки RLS:

Заключение

Мы рассмотрели способ настройки RLS "по реквизиту пользователя" через параметры сеанса. Это наиболее производительный и правильный метод. Избегайте прямых обращений к реквизитам через точку в RLS и помните, что для корректной работы ограничений необходимо исключить пересечение с ролями, дающими полные права на чтение этого объекта.

← На главную