Почему RLS в БСП работает в списках, но не фильтрует записи в запросах, и как это исправить?

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

При разработке конфигураций на базе Библиотеки стандартных подсистем (БСП) разработчики часто сталкиваются с ситуацией, когда ограничение доступа на уровне записей (RLS) ведет себя непоследовательно. В формах списков мы видим только разрешенные данные, но стоит выполнить запрос в консоли или программном коде с использованием ключевого слова ВЫБРАТЬ РАЗРЕШЕННЫЕ, как в результат попадают записи, которые пользователь видеть не должен. При этом вместо ссылок на объекты отображается надпись "Объект не найден".

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

Причина 1. Особенности "производительного режима" RLS

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

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

Решение 1. Принудительное наложение фильтра через обращение к полям

Одним из самых быстрых способов заставить платформу выполнить проверку прав принудительно является обращение к любому полю объекта через точку в секции ГДЕ. Рассмотрим пример. Если у нас есть регистр сведений, где измерение Контрагент ограничено по RLS, обычный запрос может вернуть лишние строки:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    МойРегистр.Контрагент,
    МойРегистр.Сумма
ИЗ
    РегистрСведений.МойРегистр КАК МойРегистр

Чтобы отсечь запрещенные записи, добавим условие, которое заставит платформу выполнить JOIN с основной таблицей справочника, где RLS работает безусловно:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    МойРегистр.Контрагент,
    МойРегистр.Сумма
ИЗ
    РегистрСведений.МойРегистр КАК МойРегистр
ГДЕ
    (НЕ МойРегистр.Контрагент.ЭтоГруппа) ИЛИ (МойРегистр.Контрагент.ЭтоГруппа)

Такое условие всегда истинно, но оно вынуждает оптимизатор запросов применить правила доступа справочника Контрагенты к выборке регистра. Также можно использовать функцию ПРЕДСТАВЛЕНИЕ(МойРегистр.Контрагент) или получать любое поле справочника в списке полей выборки.

Решение 2. Проверка корректности внедрения БСП и обновление данных

Часто проблема кроется в том, что для конкретного регистра не были сформированы Ключи доступа. Если система "не видит" правил, по которым нужно фильтровать записи в конкретной выборке, она вернет все строки. Выполним проверку по шагам:

  1. Проанализируем наличие регистра в справочнике ИдентификаторыОбъектовМетаданных. Если объекта там нет или он помечен как удаленный, механизмы БСП работать не будут.
  2. Убедимся, что тип нашего регистра включен в определяемые типы БСП, такие как ВладелецОбъектаДоступа или ОбъектДоступа. Без этого система не будет генерировать записи в технических регистрах КлючиДоступаКОбъектам и КлючиДоступаКРегистрам.
  3. Запустим обновление вспомогательных данных. Это можно сделать, запустив сеанс 1С с параметром командной строки: /C ЗапуститьОбновлениеИнформационнойБазы.
  4. Воспользуемся внешней обработкой "Проверка внедрения БСП" (идет в составе дистрибутива библиотеки). Она покажет, нет ли ошибок в модуле менеджера регистра в процедуре ПриЗаполненииОграниченияДоступа.

Решение 3. Индексация полей и шаблоны RLS в ролях

Для корректной работы производительного режима RLS измерения, по которым наложено ограничение, обязательно должны быть индексированы. Отсутствие индекса по полю ИзмерениеСсылкаНаСправочник может привести к тому, что платформа проигнорирует таблицы ключей доступа для оптимизации скорости.

Проверим код в модуле менеджера регистра. Он должен выглядеть примерно так:


Процедура ПриЗаполненииОграниченияДоступа(Ограничение) Экспорт
    Ограничение.Текст =
    "РазрешитьЧтениеИзменение
    |ГДЕ
    | ЗначениеРазрешено(ИзмерениеСсылкаНаСправочник)";
КонецПроцедуры

А в самой роли для этого регистра должно быть прописано ограничение с использованием стандартных шаблонов БСП. Посмотрим на пример правильной настройки в роли:


#Если &ОграничениеДоступаНаУровнеЗаписейУниверсально #Тогда
    #ДляРегистра("ИдентификаторыОбъектовМетаданных.РегистрСведенийМойРегистр", "ИзмерениеСсылкаНаСправочник", "", "", "", "")
#Иначе
    #ПоЗначениям( "РегистрСведений.МойРегистр", "", "", "МойВидДоступа", "ИзмерениеСсылкаНаСправочник", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","")
#КонецЕсли

Почему в формах списка всё работает правильно?

Выясним причину, по которой динамические списки отображают данные корректно, а запросы — нет. Динамические списки платформы 1С используют собственные механизмы построения запросов. Они автоматически добавляют выборку представлений и полей, необходимых для отрисовки интерфейса. Это неявно активирует те самые механизмы "принудительного" RLS, о которых мы говорили в первом решении. Прямой же запрос в консоли максимально "сырой", и если вы не обратились к полям связанного объекта, платформа выбирает данные из физической таблицы регистра напрямую, минуя фильтры связанных таблиц.

Важный момент: Если вы используете составной тип данных в измерении, стандартный шаблон #ДляРегистра может работать нестабильно. В этом случае рекомендуется явно указывать типы в коде модуля менеджера или ограничивать использование составных типов в полях, подлежащих фильтрации по RLS.

Подводя итог: для исправления работы RLS в запросах, во-первых, обеспечьте актуальность ключей доступа через обновление информационной базы, а во-вторых, при написании программных запросов всегда обращайтесь к полям ограничиваемых объектов (через точку) или используйте функцию ПРЕДСТАВЛЕНИЕ, чтобы активировать механизм фильтрации платформы.

← На главную