Почему параметры сеанса в RLS не работают в отчетах и как это исправить?

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

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

В этой статье мы разберем, почему возникает этот «глюк», как работает архитектура фоновых заданий в 1С и какие существуют проверенные способы решения данной проблемы.

Суть проблемы и механизм возникновения

Рассмотрим типичную ситуацию. В системе настроено ограничение на чтение регистра накопления. Текст ограничения выглядит следующим образом:

ТекТаб ГДЕ ТекТаб.Сотрудник = &ТекущийСотрудник

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

Проанализируем причину такого поведения. В современных версиях платформы 1С:Предприятие 8.3 отчеты по умолчанию формируются в фоновом задании. С точки зрения архитектуры платформы, фоновое задание — это отдельный сеанс на сервере.

Когда мы выполняем код:

ПараметрыСеанса.ТекущийСотрудник = ВыбранныйСотрудник;

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

Способ 1. Отключение фонового формирования отчета

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

Разберем, как это сделать:

  1. Откройте форму отчета.
  2. В свойствах формы или в настройках схемы компоновки данных можно управлять режимом формирования.
  3. Для программного отключения можно в коде формы перед формированием установить свойство ВыполнятьВФоновомЗадании в значение Ложь (если используется стандартная подсистема «Варианты отчетов»).

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

Способ 2. Использование промежуточного хранилища в базе данных

Чтобы фоновое задание могло «подхватить» актуальное значение, измененное пользователем, это значение должно быть сохранено где-то в базе данных. Рассмотрим алгоритм реализации через Регистр сведений.

Проанализируем шаги реализации:

  1. Создаем регистр сведений НастройкиПользователейСеанса с измерениями Пользователь (или НомерСеанса) и ресурсом ЗначениеПараметра.
  2. При изменении параметра в интерфейсе, записываем новое значение в этот регистр.
  3. В модуле сеанса, в процедуре УстановкаПараметровСеанса, добавляем логику чтения из этого регистра.

Пример кода в модуле сеанса:


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

Поскольку фоновое задание при старте вызовет этот код, оно получит актуальное значение из базы данных, и RLS в отчете отработает корректно.

Способ 3. Пересмотр архитектуры RLS

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

Однако, если стоит задача именно жесткого ограничения прав (чтобы пользователь физически не мог увидеть данные другого сотрудника), рекомендуется привязывать RLS к объектам, которые имеют физическое отражение в БД (например, справочник ГруппыДоступа или НастройкиПрав), а не к динамически меняющимся переменным в памяти сеанса.

Резюме

Проблема «глюка» RLS в отчетах — это не ошибка платформы, а следствие изоляции сеансов. При изменении параметров сеанса помните, что фоновое задание — это новый сеанс. Чтобы отчет «видел» ваши изменения, всегда обеспечивайте передачу этого состояния через базу данных или отключайте фоновое выполнение отчета.

← На главную