Как получить реквизиты объекта через параметры сеанса в настройках прав доступа (RLS)

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

При настройке ограничений доступа на уровне записей (RLS) разработчики часто сталкиваются с необходимостью фильтрации данных по реквизитам текущего пользователя. Типичный пример: ограничить видимость документов только тем подразделением, к которому привязан текущий пользователь. Однако простая попытка написать условие вида Подразделение = &ТекущийПользователь.Подразделение в конструкторе ограничений прав доступа приводит к ошибке или неработоспособности правила. Разберем подробно, почему так происходит, и как правильно решить эту задачу тремя разными способами.

Почему прямое обращение через «точку» не работает

Давайте проанализируем ситуацию с точки зрения платформы 1С:Предприятие 8.3. Когда мы пишем запрос в обычном коде, платформа автоматически выполняет LEFT JOIN к соответствующим таблицам при обращении через точку. В механизме RLS ситуация иная. Оптимизатор запросов должен преобразовать ваше условие в максимально эффективный SQL-запрос, который будет добавляться к каждому обращению к защищаемой таблице.

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

Решение 1. Использование подзапросов в тексте ограничения

Рассмотрим первый способ, который позволяет обойти ограничение без изменения метаданных конфигурации. Мы можем использовать классический подзапрос SQL прямо в поле условия RLS. Вместо того чтобы пытаться «вытащить» подразделение из ссылки, мы обращаемся напрямую к таблице справочника Пользователи.

Схема условия будет выглядеть следующим образом:


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

Преимущества этого метода:

  1. Не нужно вносить изменения в структуру параметров сеанса.
  2. Подходит для быстрого исправления прав «на лету».

Недостатки:

Решение 2. Использование конструкции ВЫРАЗИТЬ

Иногда платформа «теряет» тип параметра сеанса, из-за чего обращение к его свойствам становится невозможным. Рассмотрим вариант с принудительным приведением типа. В тексте ограничения можно попробовать использовать функцию ВЫРАЗИТЬ.

Пример синтаксиса:


ГДЕ Подразделение = ВЫРАЗИТЬ(&ТекущийПользователь КАК Справочник.Пользователи).Подразделение

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

Решение 3. Создание специализированного параметра сеанса (Рекомендуемый путь)

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

Разберем этот процесс по шагам:

  1. Создание параметра: В дереве метаданных перейдем в раздел Общие -> Параметры сеанса и создадим новый параметр, например, ТекущееПодразделение с типом СправочникСсылка.Подразделения.
  2. Инициализация: Откроем модуль сеанса и в процедуре УстановкаПараметровСеанса пропишем логику заполнения этого параметра:
    
    Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
        Если ТребуемыеПараметры = Неопределено Или ТребуемыеПараметры.Найти("ТекущееПодразделение") <> Неопределено Тогда
            ПараметрыСеанса.ТекущееПодразделение = ПоискПодразделенияПользователя(ПараметрыСеанса.ТекущийПользователь);
        КонецЕсли;
    КонецПроцедуры
    
  3. Применение в RLS: Теперь наше условие в настройках прав станет максимально простым и быстрым: ГДЕ Подразделение = &ТекущееПодразделение

Почему это лучше? В этом случае SQL-сервер получает готовое значение (GUID подразделения) и делает прямое сравнение без лишних JOIN или подзапросов. Это дает колоссальный прирост скорости на больших таблицах.

Особенности работы с несколькими значениями

Как мы выяснили, у пользователя может быть несколько подразделений (например, при совмещении должностей). В таком случае использование одиночного параметра сеанса не решит задачу. Разберем, как поступить в этой ситуации:

1. Установим тип параметра сеанса как ФиксированныйМассив.
2. В модуле сеанса соберем все доступные пользователю подразделения в этот массив.
3. В условии RLS будем использовать оператор В:

ГДЕ Подразделение В (&ДоступныеПодразделенияПользователя)

Проблема внезапного отказа работы RLS

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

Всегда проверяйте, чтобы процедура УстановкаПараметровСеанса корректно отрабатывала для любых видов соединений, включая фоновые и внешние (COM, WS).

Использование возможностей БСП

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

← На главную