Почему не работает RLS для справочника в 1С и как правильно ограничить доступ к записям

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

Механизм ограничения доступа на уровне записей (RLS — Row-Level Security) в платформе «1С:Предприятие» — мощный инструмент, позволяющий гибко разграничивать права пользователей. Однако разработчики, особенно начинающие, часто сталкиваются с ситуацией, когда свеженаписанное правило RLS для справочника попросту отказывается работать. Пользователи продолжают видеть запрещенные элементы, либо, напротив, теряют доступ к справочнику целиком.

В этой статье мы подробно разберем, почему простые условия в духе ГДЕ НЕ Наименование = "Оптовая" не работают, как платформа объединяет роли, какую роль в этом играет БСП (Библиотека стандартных подсистем) и как правильно решать подобные задачи без ущерба для производительности системы.

Причина №1: Коварный принцип сложения ролей (Логическое «ИЛИ»)

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

Выясним причину. Дело в том, что права доступа в платформе «1С:Предприятие» всегда работают по принципу сложения (логическое «ИЛИ»). Рассмотрим этот механизм подробнее:

Проанализируем простую схему взаимодействия ролей:


// Роль 1 (Продавец): Чтение "ВидыЦен" -> Без ограничений (Разрешено ВСЁ)
// Роль 2 (ОграничениеЦен): Чтение "ВидыЦен" -> ГДЕ НЕ Наименование = "Оптовая"

// Итог для пользователя с обеими ролями:
// Результат = Роль 1 ИЛИ Роль 2 = Разрешено ВСЁ. RLS не работает!

Именно поэтому бесполезно создавать новую «ограничивающую» роль и просто добавлять её пользователю, у которого уже есть стандартные роли (например, «Продавец» или «Менеджер по продажам»), дающие доступ к этому же справочнику.

Причина №2: Ключевое слово РАЗРЕШЕННЫЕ в запросах

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

Если в роли настроен RLS, любой запрос к этой таблице баз данных должен явно указывать платформе, что необходимо выбирать только доступные записи. Для этого используется ключевое слово РАЗРЕШЕННЫЕ (в англоязычном варианте — ALLOWED).

Посмотрим на пример неправильного запроса в коде:


// Такой запрос вызовет ошибку нарушения прав доступа, если сработает RLS
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ВидыЦен.Ссылка КАК Ссылка
    |ИЗ
    |	Справочник.ВидыЦен КАК ВидыЦен";
ТаблицаДанных = Запрос.Выполнить().Выгрузить();

А вот так выглядит правильный, безопасный запрос, который вернет только те элементы, которые разрешены настроенным RLS:


// Данный запрос отработает без ошибок и вернет отфильтрованный результат
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ РАЗРЕШЕННЫЕ
    |	ВидыЦен.Ссылка КАК Ссылка
    |ИЗ
    |	Справочник.ВидыЦен КАК ВидыЦен";
ТаблицаДанных = Запрос.Выполнить().Выгрузить();

В динамических списках (на управляемых формах) платформа обычно подставляет ключевое слово РАЗРЕШЕННЫЕ автоматически, но в произвольных запросах отчетов, обработок и серверных модулей об этом должен заботиться разработчик.

Причина №3: Настройка полей RLS («Все поля» против отдельных полей)

В конструкторе ограничений доступа платформы можно выбрать, на какие именно поля накладывается ограничение: на «Все поля» или на конкретные (например, только на реквизит Наименование или Ссылка).

Запомните золотое правило: если вы настраиваете ограничение на чтение записи в целом, всегда выбирайте вариант «Все поля».

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

Причина №4: Использование БСП и производительного режима RLS (Кэширование данных)

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

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

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

Чтобы изменения заработали, необходимо выполнить обновление вспомогательных данных доступа. Сделать это можно несколькими способами:

  1. Запустить регламентное задание «Обновление доступа на уровне записей».
  2. В режиме «1С:Предприятие» открыть обработку «Инструменты разработчика» (или аналогичную административную панель БСП) и запустить обновление вспомогательных данных.
  3. Программно вызвать обновление ключей доступа с помощью встроенных функций БСП:

// Вызов обновления прав доступа средствами БСП
УправлениеДоступомСлужебный.ОбновитьДоступНаУровнеЗаписей();

Почему фильтрация по наименованию (ГДЕ НЕ Наименование = "...") — это грубая ошибка

В первом сообщении темы автор пытается применить условие:

ГДЕ НЕ ВидыЦен.Наименование = "Оптовая"

Давайте проанализируем, почему такое решение является грубым антипаттерном программирования в среде 1С, и к каким последствиям оно приведет.

Во-первых, это уязвимость безопасности. Текстовое наименование — это крайне нестабильный реквизит. Любой пользователь, имеющий права на редактирование справочника ВидыЦен, может случайно или намеренно изменить наименование «Оптовая» на «Оптовая цена» или просто добавить в конец лишний пробел. Условие RLS тут же перестанет срабатывать, и скрытые данные станут доступны пользователям, которые не должны их видеть.

Во-вторых, это колоссальный удар по производительности СУБД. Использование оператора отрицания НЕ (или <>) в запросах RLS блокирует использование индексов базовых таблиц на уровне СУБД (MS SQL, PostgreSQL). Чтобы выполнить такой запрос, серверу СУБД придется выполнить полное сканирование таблицы (Table Scan) вместо быстрого поиска по индексу. На больших базах данных это мгновенно приведет к зависанию системы и блокировкам при попытке любого пользователя обратиться к справочнику.

Как правильно ограничить элементы?

ГДЕ НЕ ВидыЦен.ЗапретитьДоступМенеджерам

Как правильно обойти ограничение сложения ролей в типовых конфигурациях

Что делать, если конфигурация находится на поддержке, изменять стандартные роли нельзя (иначе возникнут проблемы при обновлениях), но ограничить доступ по RLS всё же необходимо?

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

  1. Перейдите в раздел Администрирование — Настройки пользователей и прав — Группы доступа.
  2. Создайте новый Профиль групп доступа.
  3. В профиле укажите виды доступа, которые подлежат ограничению (например, «Виды цен» или «Организации»).
  4. Создайте Группу доступа на основании этого профиля и включите туда нужных пользователей.
  5. В настройках ограничений группы доступа укажите конкретные виды цен, к которым разрешен или запрещен доступ. БСП сама динамически соберет ограничения и запишет их в регистры ключей доступа, минуя ограничения стандартных ролей платформы.

Если же типовых механизмов БСП не хватает, альтернативным решением является проверка прав программным путем непосредственно в коде (например, в модуле объекта при записи или в модуле менеджера при выборе данных). Такой подход избавляет от необходимости писать сложные, нечитаемые шаблоны RLS в конфигураторе.


Процедура ПередЗаписью(Отказ)
    // Проверка прав программным кодом вместо RLS
    Если ЭтотОбъект.Наименование = "Оптовая" И НЕ РольДоступна("ПолныеПрава") Тогда
        Отказ = Истина;
        ВызватьИсключение "У вас нет прав на изменение оптовых цен!";
    КонецЕсли;
КонецПроцедуры

Бонус: Что за «интерфейсы с пустыми телами» используются в 1С?

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

Речь идет о Переопределяемых общих модулях (общие модули с суффиксом Переопределяемый, например, УправлениеДоступомПереопределяемый, ОбщегоНазначенияПереопределяемый).

Давайте разберем, как устроен этот механизм:

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

← На главную