Как поставить запрет на использование документов для пользователей, исходя из реквизита справочника?

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

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

В этой статье мы подробно разберем несколько способов реализации такой задачи — от простых косметических ограничений на уровне интерфейса до надежных систем разграничения прав на уровне СУБД (RLS) и инструментов Библиотеки стандартных подсистем (БСП).

Способ 1. Ограничение на уровне форм (Интерфейсный метод)

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

Рассмотрим по шагам, как это реализовать:

  1. Создаем новое расширение конфигурации.
  2. Добавляем в расширение форму нужного документа (например, форму объекта и форму списка).
  3. В модуле формы объекта перехватываем событие ПриСозданииНаСервере с помощью аннотации &После или &Вместо.

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


&НаСервере
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
    
    ТекущийПользователь = Пользователи.ТекущийПользователь();
    ДолжностьПользователя = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ТекущийПользователь, "Должность");
    
    ЗапрещеннаяДолжность = Справочники.Должности.НайтиПоНаименованию("Менеджер по закупкам");
    
    Если ДолжностьПользователя = ЗапрещеннаяДолжность Тогда
        // Первый вариант: полностью блокируем открытие формы объекта
        Отказ = Истина;
        ВызватьИсключение "У вас нет прав на просмотр данного документа согласно вашей должности!";
    КонецЕсли;

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

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


&НаСервере
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
    
    ТекущийПользователь = Пользователи.ТекущийПользователь();
    ДолжностьПользователя = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ТекущийПользователь, "Должность");
    
    Если ДолжностьПользователя = Справочники.Должности.НайтиПоНаименованию("Стажер") Тогда
        // Второй вариант: открываем форму только для чтения
        ЭтаФорма.ТолькоПросмотр = Истина;
    КонецЕсли;

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

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

Способ 2. Использование классического RLS (Row-Level Security)

Для надежного сокрытия данных необходимо использовать механизм ограничения доступа на уровне записей — RLS. В этом случае СУБД сама отсекает «лишние» строки данных еще на этапе выполнения SQL-запроса, и пользователь физически не сможет прочитать документ ни в отчетах, ни в списках.

Проанализируем классическую ошибку проектирования RLS, которую часто допускают начинающие разработчики. Попытка написать RLS-запрос с обращением к реквизитам пользователя «через точку» (например, &ТекущийПользователь.Должность) приведет к критическому падению производительности СУБД. При каждом чтении документов база данных будет вынуждена делать неявное левое соединение (LEFT JOIN) с таблицей пользователей, что парализует работу системы на больших объемах данных.

Правильное решение состоит из двух шагов: использование параметров сеанса и оптимизация самого RLS-запроса.

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

Мы создаем параметр сеанса ТекущаяДолжностьПользователя (тип ссылки на справочник должностей). Инициализируем его один раз при старте системы в модуле сеанса:


Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
    
    Если ТребуемыеПараметры.Найти("ТекущаяДолжностьПользователя") <> Неопределено Тогда
        
        ИмяПользователяИБ = ПользователиИнформационнойБазы.ТекущийПользователь().Имя;
        СотрудникСправочник = Справочники.Пользователи.НайтиПоРеквизиту("ИдентификаторПользователяИБ", ПользователиИнформационнойБазы.ТекущийПользователь().УникальныйИдентификатор);
        
        Если ЗначениеЗаполнено(СотрудникСправочник) Тогда
            ПараметрыСеанса.ТекущаяДолжностьПользователя = СотрудникСправочник.Должность;
        Иначе
            ПараметрыСеанса.ТекущаяДолжностьПользователя = Справочники.Должности.ПустаяСсылка();
        EndIf;
        
    КонецЕсли;

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

Шаг 2. Написание RLS-ограничения в роли

Переходим к настройке роли в конфигураторе. Для нашего документа настраиваем ограничение на право Чтение. В тексте ограничения мы сравниваем реквизиты документа напрямую с подготовленным параметром сеанса:


Документ.ЗаказКлиента ГДЕ 
    НЕ &ТекущаяДолжностьПользователя = ЗНАЧЕНИЕ(Справочник.Должности.Бухгалтер)

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


ЗаказКлиента ГДЕ Ссылка В 
    (ВЫБРАТЬ РегистрДоступа.ОбъектСсылка 
     ИЗ РегистрСведений.МатрицаДоступа КАК РегистрДоступа 
     ГДЕ РегистрДоступа.Должность = &ТекущаяДолжностьПользователя)

Способ 3. Интеграция с механизмами БСП (Виды доступа)

Если вы работаете в современной типовой конфигурации (например, «Управление торговлей 11», «ERP Управление предприятием» или «Комплексная автоматизация»), ручное написание RLS-запросов считается плохой практикой. В этих конфигурациях используется Библиотека стандартных подсистем (БСП), которая предоставляет более мощный, гибкий и производительный функционал.

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

Давайте разберем, как правильно встроить ограничение по должностям в экосистему БСП:

  1. Регистрация нового вида доступа. В общем модуле УправлениеДоступомПереопределяемый находим процедуру ПриЗаполненииВидовДоступа и регистрируем наш новый вид доступа — «Должности».
  2. Настройка роли в конфигураторе. Для нужного документа в роли прописываем стандартный шаблон БСП:
    
    #ПоЗначениям("Документ.ЗаказКлиента", "Чтение", "", "Должности", "Должность", "", "", "", "", "", "", "", "", "")
    
    Этот шаблон сообщает системе БСП, что чтение документа должно контролироваться по значению реквизита «Должность» текущего объекта.
  3. Администрирование в режиме Предприятия. После этого в режиме «1С:Предприятие» в справочнике «Группы доступа» администраторы смогут настраивать права для пользователей по должностям в удобном визуальном интерфейсе. Система БСП сама возьмет на себя оптимизацию запросов к СУБД и обеспечение максимального быстродействия.

Резюме и рекомендации

Выбор конкретного метода зависит от архитектуры вашей базы данных и требований к безопасности:

← На главную