Настройка ограничений доступа на уровне записей (RLS) — одна из наиболее сложных и ответственных задач при проектировании прав доступа в системе «1С:Предприятие». Часто разработчики сталкиваются с ситуацией, когда казалось бы правильно настроенные права на отдельные поля ведут себя непредсказуемо во встроенном языке. Классический пример: мы разрешили чтение полей Ссылка и Наименование, но закрыли доступ к остальным («прочим») полям. При попытке прочитать наименование через точку от ссылки в коде мы неожиданно получаем пустую строку.
В этой статье мы подробно проанализируем, почему так происходит, разберем внутренние механизмы платформы 1С и СУБД, а также научимся правильно обходить это ограничение с помощью запросов.
Для начала давайте разберем, для чего вообще применяется схема разделения полей в RLS. В типовых конфигурациях часто возникает задача скрыть конфиденциальную информацию (например, цены номенклатуры, контактные данные контрагентов или комментарии к документам), но при этом сохранить целостность интерфейса.
Если мы полностью закроем объект для чтения пользователю, то во всех связанных объектах, отчетах и динамических списках он увидит крайне неинформативную надпись <Объект не найден...> (так называемые «битые ссылки»). Чтобы избежать этого визуального дефекта, применяется следующий прием настройки прав на чтение объекта:
Ссылка, Наименование и Код (или Дата и Номер для документов) ограничение RLS оставляется пустым или настраивается как ГДЕ ИСТИНА. Это значит, что базовая информация об объекте всегда доступна для чтения.<Прочие поля> (куда входят все остальные реквизиты, табличные части и свойства) устанавливается ограничение ГДЕ ЛОЖЬ. Это наглухо закрывает доступ к детальной информации.При такой настройке пользователь видит красивые и понятные представления ссылок в интерфейсе, но не может открыть карточку элемента или посмотреть его конфиденциальные реквизиты.
Рассмотрим ситуацию, когда разработчик пытается получить разрешенное поле (например, Наименование) через обращение к ссылке во встроенном языке:
// Попытка получить наименование элемента через объектную модель
ИмяЭлемента = СсылкаНаОбъект.Наименование;
КомментарийЭлемента = СсылкаНаОбъект.Комментарий;
В отладчике мы увидим странную картину: и Наименование, и Комментарий, и все прочие реквизиты будут абсолютно пустыми, хотя на Наименование у нас есть явное право просмотра, а сам элемент физически существует в базе данных. Ошибки нарушения прав при этом не возникает.
Давайте разберем по шагам, что происходит в этот момент под капотом платформы:
СсылкаНаОбъект.Наименование) или вызов метода ПолучитьОбъект() инициирует обращение к объектному кэшу платформы 1С.<Прочие поля>) действует жесткое ограничение ГДЕ ЛОЖЬ, СУБД возвращает платформе отказ в доступе на чтение всей записи, так как в выборку попали запрещенные колонки.Важное правило: объектный метод работы с данными в 1С всегда требует полного доступа ко всей записи. Если хотя бы одно поле закрыто через RLS, объектный кэш не будет построен, и все реквизиты вернутся пустыми.
Единственным правильным решением для обхода этой особенности является использование явных запросов к базе данных. В отличие от объектной модели, механизм запросов позволяет гибко управлять составом выбираемых полей.
Проанализируем пример правильного кода для получения разрешенных данных:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Наименование КАК Наименование
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", СсылкаНаОбъект);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
// Здесь мы гарантированно получим корректное заполненное наименование
ИмяЭлемента = Выборка.Наименование;
Иначе
ИмяЭлемента = "";
КонецЕсли;
Почему этот подход работает успешно?
Ссылка, Наименование). Запрещенные «прочие поля» в запросе отсутствуют.РАЗРЕШЕННЫЕ. Оно указывает платформе, что из выборки нужно молча исключить те записи, на чтение которых у пользователя вообще нет прав (например, если закрыт доступ даже к самой Ссылке). Если этого ключевого слова не будет, запрос вызовет ошибку нарушения прав доступа.ГДЕ ЛОЖЬ не накладывается на результат, так как закрытые поля не участвуют в выборке.Хотя разделение прав доступа по полям позволяет создавать дружелюбный интерфейс без «битых ссылок», важно помнить о цене такого решения. Ограничение доступа на уровне отдельных колонок (полей) создает колоссальную нагрузку на СУБД.
Для каждого проверяемого поля платформа вынуждена генерировать сложные вложенные подзапросы с многочисленными соединениями (LEFT JOIN). В высоконагруженных базах данных со многими тысячами записей это неизбежно приводит к сильному замедлению работы отчетов и динамических списков.
В современных конфигурациях, построенных на базе Библиотеки стандартных подсистем (БСП), разработчики постепенно уходят от классического RLS по полям в пользу производительного RLS. При этом режиме:
Если специфика вашего проекта все же требует использования классического RLS с разделением полей, всегда помните о золотом правиле разработчика 1С: любое чтение данных в условиях активного RLS должно выполняться исключительно через запросы с явным перечислением полей и ключевым словом РАЗРЕШЕННЫЕ. Это убережет ваши алгоритмы от получения пустых значений и обеспечит стабильную работу системы.