RLS в 1С — почему слетают права и зависает проведение в Бухгалтерии

Почему RLS в 1С — это не просто «галочка в настройках»
Механизм Row Level Security (RLS) — ограничение доступа на уровне записей — один из самых мощных и одновременно самых коварных инструментов платформы 1С:Предприятие 8. Когда он настроен правильно, пользователь видит ровно те данные, которые ему положены: свои заказы, свои контрагенты, свои склады. Когда настроен с ошибкой — менеджер Иванов спокойно открывает документы менеджера Петрова, а директор филиала видит выручку всей компании.
Коротко: Права «слетают», когда пользователю назначено несколько ролей и хотя бы одна из них не ограничивает объект — итог считается по ИЛИ, ограничение обнуляется. Проведение зависает из-за тяжёлых RLS-условий: подзапросы к регистрам и обращения через Ссылка.Реквизит внутри шаблона превращаются в JOIN-ы на каждую строку. Решение: сделать ограничения одинаковыми во всех ролях, вынести списки доступа в параметры сеанса (СписокЗначений) вместо подзапросов и проверять RLS-выражения после каждого обновления конфигурации.
Проблема усугубляется тем, что ошибки RLS не бросаются в глаза. Система не падает с ошибкой, не пишет в журнал регистрации критических событий. Пользователь просто видит данные — и не подозревает, что видит лишнее. Администратор тоже не замечает, потому что сам работает с полными правами.
В этой статье мы разберём шесть наиболее распространённых ошибок при настройке RLS, покажем, как они выглядят в коде шаблонов ограничений, и объясним, как каждую из них исправить. Если вы хотите делегировать эту работу профессионалу — найти разработчика 1С можно на нашей бирже.
Ошибка №1: Пустой шаблон ограничения — доступ открыт всем
Как это выглядит
Самая «детская» и при этом крайне распространённая ошибка. Администратор создаёт роль, переходит на вкладку «Ограничения доступа к данным», добавляет ограничение для объекта — и оставляет поле шаблона пустым или вводит туда текст, который всегда возвращает ИСТИНА.
В конфигураторе это выглядит так: объект добавлен в список ограничений, флажок «Ограничить» установлен, но в поле условия написано просто:
ИСТИНА
Или ещё хуже — поле вообще не заполнено, и платформа интерпретирует пустое условие как «разрешить всё».
Почему это опасно
Пользователь с такой ролью получает доступ ко всем записям объекта без исключения. При этом в правах роли формально написано «ограничен» — и администратор уверен, что всё настроено. Аудит безопасности покажет наличие ограничения, но не его содержимое.
Как исправить
Всегда проверяйте текст условия после сохранения. Минимально корректное ограничение для фильтрации по менеджеру выглядит так:
// Шаблон ограничения: Документ.РеализацияТоваровУслуг.Чтение
// Условие: пользователь видит только свои документы
{ГДЕ
(ТекущаяТаблица.Менеджер = &ТекущийПользователь)
}
А параметр &ТекущийПользователь должен быть установлен в сеансовых данных:
// Модуль сеанса — установка параметров сеанса
Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
// Устанавливаем текущего пользователя для RLS
ПараметрыСеанса.ТекущийПользователь = Справочники.Пользователи.НайтиПоРеквизиту(
"ПользовательИБ",
ПользователиИнформационнойБазы.ТекущийПользователь()
);
КонецПроцедуры
Ошибка №2: Отсутствие ограничения на табличные части
Суть проблемы
Разработчик добавляет ограничение на чтение шапки документа, но забывает про его табличные части. В платформе 1С ограничения на основную таблицу и таблицы табличных частей настраиваются отдельно. Если ограничить только шапку, пользователь не увидит документ в списке — но сможет получить данные строк через запрос напрямую к таблице табличной части.
Пример уязвимости
Представьте: у вас настроено ограничение на Документ.ЗаказКлиента — пользователь видит только заказы своего менеджера. Но ограничение на Документ.ЗаказКлиента.Товары не установлено. Тогда следующий запрос вернёт строки чужих заказов:
// ВНИМАНИЕ: этот запрос обходит RLS на шапку документа!
// Данные табличной части доступны без ограничения
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Товары.Номенклатура,
| Товары.Количество,
| Товары.Цена,
| Товары.Ссылка КАК Документ
|ИЗ
| Документ.ЗаказКлиента.Товары КАК Товары";
Результат = Запрос.Выполнить();
// Пользователь получит строки ВСЕХ заказов, не только своих!
Правильная настройка
Для каждого объекта с табличными частями необходимо добавлять ограничения на каждую таблицу отдельно. Условие для табличной части обычно повторяет условие шапки, но обращается к полю через точку:
// Шаблон ограничения для табличной части: Чтение
// Объект: Документ.ЗаказКлиента.Товары
{ГДЕ
(ТекущаяТаблица.Ссылка.Менеджер = &ТекущийПользователь)
}
Обратите внимание: ТекущаяТаблица.Ссылка — это ссылка на документ-владелец табличной части. Через неё можно обращаться к любым реквизитам шапки.
Ошибка №3: Некорректная логика «ИЛИ» в условиях ограничения
Как возникает ошибка
Когда пользователь должен видеть данные по нескольким критериям одновременно (например, свои документы или документы своего подразделения), разработчики часто строят условие через ИЛИ. Ошибка возникает, когда одна из ветвей условия оказывается всегда истинной из-за некорректной проверки на NULL или пустое значение.
// НЕПРАВИЛЬНО: если ОтветственноеПодразделение не заполнено,
// условие справа от ИЛИ всегда истинно — пользователь видит всё!
{ГДЕ
(ТекущаяТаблица.Менеджер = &ТекущийПользователь)
ИЛИ (ТекущаяТаблица.Подразделение = &ПодразделениеПользователя)
}
Если параметр &ПодразделениеПользователя не установлен или установлен в пустую ссылку, а в документах поле «Подразделение» тоже пустое — условие ТекущаяТаблица.Подразделение = &ПодразделениеПользователя вернёт ИСТИНА для всех записей с пустым подразделением. В зависимости от данных это может открыть доступ к большей части базы.
Правильный подход
Всегда явно проверяйте, что параметр не пустой, прежде чем использовать его в условии:
// ПРАВИЛЬНО: проверяем заполненность параметра
{ГДЕ
(ТекущаяТаблица.Менеджер = &ТекущийПользователь)
ИЛИ (
&ПодразделениеПользователя <> ЗНАЧЕНИЕ(Справочник.Подразделения.ПустаяСсылка)
И ТекущаяТаблица.Подразделение = &ПодразделениеПользователя
)
}
И в модуле сеанса добавьте защитную проверку:
Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
Пользователь = Справочники.Пользователи.НайтиПоРеквизиту(
"ПользовательИБ",
ПользователиИнформационнойБазы.ТекущийПользователь()
);
ПараметрыСеанса.ТекущийПользователь = Пользователь;
// Устанавливаем подразделение только если пользователь найден
Если НЕ Пользователь.Пустая() Тогда
ПараметрыСеанса.ПодразделениеПользователя = Пользователь.ОсновноеПодразделение;
Иначе
// Пустая ссылка — пользователь не увидит ничего лишнего
ПараметрыСеанса.ПодразделениеПользователя =
Справочники.Подразделения.ПустаяСсылка();
КонецЕсли;
КонецПроцедуры
Ошибка №4: Забытые регистры и виртуальные таблицы
Регистры остаются без ограничений
Классический сценарий: разработчик настраивает RLS на справочники и документы, но забывает про регистры. Между тем регистры накопления, регистры сведений и регистры бухгалтерии хранят огромные массивы аналитических данных — обороты, остатки, проводки.
Пользователь, у которого закрыт доступ к документам продаж, может через регистр накопления «Продажи» получить все обороты по всем контрагентам. Это особенно актуально для конфигураций на базе 1С:Бухгалтерия на Кодерион, где регистры бухгалтерии содержат полную финансовую картину.
Виртуальные таблицы — отдельная история
Ещё тоньше проблема с виртуальными таблицами регистров (Остатки, Обороты, ОстаткиИОбороты). Ограничение, настроенное на основную таблицу регистра, не распространяется автоматически на виртуальные таблицы. Их нужно ограничивать отдельно.
// Шаблон ограничения для основной таблицы регистра:
// РегистрНакопления.Продажи.Чтение
{ГДЕ
(ТекущаяТаблица.Менеджер = &ТекущийПользователь)
}
// Этот шаблон НЕ защищает виртуальные таблицы!
// Нужно отдельно добавить ограничение для:
// РегистрНакопления.Продажи.Остатки
// РегистрНакопления.Продажи.Обороты
// РегистрНакопления.Продажи.ОстаткиИОбороты
Для виртуальных таблиц условие аналогично, но обращение к полям идёт без префикса основной таблицы:
// Шаблон ограничения для виртуальной таблицы:
// РегистрНакопления.Продажи.Обороты.Чтение
{ГДЕ
(ТекущаяТаблица.Менеджер = &ТекущийПользователь)
}
Чек-лист объектов для ограничения
- Справочники (основная таблица)
- Документы (основная таблица + все табличные части)
- Регистры накопления (основная таблица + Остатки + Обороты + ОстаткиИОбороты)
- Регистры сведений (основная таблица + срезы)
- Регистры бухгалтерии (основная таблица + виртуальные таблицы)
- Планы видов характеристик
- Бизнес-процессы и задачи
Ошибка №5: Конфликт нескольких ролей — расширение вместо пересечения
Как работает объединение ролей в 1С
Это одна из самых концептуально сложных ошибок. Когда пользователю назначено несколько ролей, платформа объединяет их права по принципу логического ИЛИ: пользователь получает максимум из того, что разрешено хотя бы в одной роли. Для обычных прав это интуитивно понятно. Но с RLS всё иначе.
Если одна роль содержит ограничение Менеджер = &ТекущийПользователь, а вторая роль на тот же объект не содержит ограничения (или содержит условие ИСТИНА) — итоговый доступ будет без ограничений. Ограничение из первой роли полностью нивелируется второй ролью.
// Роль «МенеджерПродаж»: ограничение на документы
// Условие: ТекущаяТаблица.Менеджер = &ТекущийПользователь
// Роль «ПросмотрОтчётов»: без ограничения на те же документы
// Условие: (пусто) = ИСТИНА
// Итог для пользователя с обеими ролями:
// ИСТИНА ИЛИ (Менеджер = ТекущийПользователь) = ИСТИНА
// Пользователь видит ВСЕ документы!
Как диагностировать проблему
Используйте встроенный инструмент платформы — «Проверка прав доступа» в конфигураторе. Но лучше напишите диагностическую процедуру:
// Диагностика: получить список ролей пользователя и их ограничений
Процедура ДиагностикаРолейПользователя(ПользовательИБ)
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Роли пользователя: " + ПользовательИБ.Имя;
Сообщение.Сообщить();
Для Каждого Роль Из ПользовательИБ.Роли Цикл
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = " - " + Роль.Роль.Имя;
Сообщение.Сообщить();
КонецЦикла;
КонецПроцедуры
Правильная архитектура ролей
Золотое правило: если объект ограничен в одной роли, он должен быть ограничен во всех ролях, которые дают к нему доступ. Никогда не оставляйте ограничение пустым в «вспомогательных» ролях — это немедленно открывает полный доступ.
Рекомендуемый подход — создать базовую роль с ограничениями и наследовать от неё, а не создавать множество независимых ролей с частичными настройками. Подробнее об архитектуре прав можно почитать в контексте задачи по 1С:ERP, где многоуровневая система доступа является нормой.
Ошибка №6: Параметры сеанса не инициализированы — доступ закрыт или открыт полностью
Два сценария одной ошибки
Параметры сеанса — это механизм, через который RLS получает «контекст» текущего пользователя. Если параметр не установлен, возможны два сценария в зависимости от настроек платформы:
- Сценарий «всё закрыто»: запрос с неинициализированным параметром возвращает пустую выборку. Пользователь видит пустые списки и думает, что данных нет. Обращается в поддержку — теряется время.
- Сценарий «всё открыто»: если условие написано с ошибкой и NULL-параметр сравнивается с полем, которое тоже может быть NULL — условие парадоксально выполняется для всех записей.
Типичная ошибка в модуле сеанса
// НЕПРАВИЛЬНО: параметр устанавливается только при определённых условиях
// Если условие не выполнено — параметр остаётся неинициализированным
Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
Пользователь = Справочники.Пользователи.НайтиПоРеквизиту(
"ПользовательИБ",
ПользователиИнформационнойБазы.ТекущийПользователь()
);
// Ошибка: параметр не устанавливается если пользователь не найден!
Если НЕ Пользователь.Пустая() Тогда
ПараметрыСеанса.ТекущийПользователь = Пользователь;
ПараметрыСеанса.ДоступныеОрганизации = Пользователь.ДоступныеОрганизации.Выгрузить();
КонецЕсли;
// Если пользователь не найден — параметры не установлены!
// При первом обращении к данным платформа выдаст ошибку
// или вернёт некорректный результат
КонецПроцедуры
Правильная инициализация с защитой
// ПРАВИЛЬНО: параметры устанавливаются всегда, даже в «безопасные» значения
Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
// Инициализируем параметры безопасными значениями по умолчанию
// Пустые ссылки гарантируют, что пользователь ничего не увидит
ПараметрыСеанса.ТекущийПользователь = Справочники.Пользователи.ПустаяСсылка();
ПараметрыСеанса.ДоступныеОрганизации = Новый СписокЗначений;
// Пытаемся найти пользователя
ПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
Если ПользовательИБ = Неопределено Тогда
// Системный пользователь или неавторизованный сеанс
// Параметры уже установлены в безопасные значения
Возврат;
КонецЕсли;
Пользователь = Справочники.Пользователи.НайтиПоРеквизиту(
"ПользовательИБ",
ПользовательИБ
);
Если Пользователь.Пустая() Тогда
// Пользователь ИБ не связан со справочником Пользователи
// Логируем проблему и оставляем безопасные значения
ЗаписьЖурналаРегистрации(
"RLS.ОшибкаИнициализации",
УровеньЖурналаРегистрации.Предупреждение,
,
,
"Пользователь ИБ не найден в справочнике: " + ПользовательИБ.Имя
);
Возврат;
КонецЕсли;
// Устанавливаем реальные значения
ПараметрыСеанса.ТекущийПользователь = Пользователь;
// Формируем список доступных организаций
ДоступныеОрганизации = Новый СписокЗначений;
Для Каждого СтрокаОрганизации Из Пользователь.ДоступныеОрганизации Цикл
ДоступныеОрганизации.Добавить(СтрокаОрганизации.Организация);
КонецЦикла;
ПараметрыСеанса.ДоступныеОрганизации = ДоступныеОрганизации;
КонецПроцедуры
Найдите специалиста для решения этой задачи на koderion.ru
Большинство этих ошибок в 1с проявляется неочевидно: то ошибка проведения в 1с бухгалтерия после релиза, то «почему слетела база 1с» при пересохранении ролей. Проверяйте RLS-выражения после каждого обновления и держите рядом разработчика, способного быстро откатить настройку.
Почему при RLS зависает проведение в Бухгалтерии
RLS не бесплатен. Каждое условие ограничения платформа подставляет в SQL-запрос, который она формирует при чтении данных. Если проведение документа читает регистры, справочники и движения, а на них навешаны ограничения — на каждый такой запрос СУБД дописывает ваш фильтр. Один документ на 200 строк табличной части может породить сотни обращений, и на каждое — дополнительный JOIN.
Что именно тормозит
Три главных источника задержек в шаблонах RLS в 1С:
- Подзапросы внутри условия. Конструкция вида
Организация В (ВЫБРАТЬ ... ИЗ РегистрСведений.НастройкиДоступа)выполняется для каждой проверяемой записи. На регистре бухгалтерии это десятки тысяч вызовов при одном проведении. - Обращения через точку.
ТекущаяТаблица.Ссылка.Организация = &Организацияразворачивается в соединение с таблицей документа. Три-четыре точки подряд — три-четыре JOIN-а. - RLS на регистре бухгалтерии. Проведение пишет проводки, а на чтение движений висит ограничение — платформа проверяет права на уже записываемые данные.
На типовой Бухгалтерии проведение реализации, которое без RLS занимало 1–2 секунды, с неоптимальными шаблонами вырастает до 15–40 секунд. Массовое перепроведение за квартал может вообще не завершиться за рабочий день.
Как ускорить
Первое — заменить подзапросы на параметры сеанса. Список доступных организаций считается один раз при старте сеанса и кладётся в СписокЗначений, а в условии остаётся простое ТекущаяТаблица.Организация В (&ДоступныеОрганизации). Это убирает подзапрос из каждой проверки.
// В шаблоне — только сравнение со списком из параметра сеанса
{ГДЕ
ТекущаяТаблица.Организация В (&ДоступныеОрганизации)
}Второе — минимизировать обращения через точку. Если фильтруете табличную часть по реквизиту шапки, вместо Ссылка.Организация лучше денормализовать поле «Организация» прямо в табличную часть на этапе доработки конфигурации — тогда фильтр идёт по своей таблице без JOIN.
Третье — проверьте, какой SQL реально уходит в СУБД. В технологическом журнале включите событие запросов, найдите свой документ и посмотрите план. Если видите вложенные подзапросы на каждую строку — узкое место в RLS-выражении, а не в бизнес-логике.
Четвёртое — не навешивайте RLS на объекты, которые в проведении читаются массово и не требуют разграничения (служебные регистры сведений, справочники курсов валют). Каждый лишний ограниченный объект в цепочке проведения — это дополнительное соединение.
Как быстро найти, из-за какой роли открылся лишний доступ
Когда пользователь видит чужие данные, а вы уверены, что «всё ограничено», причина почти всегда в объединении ролей по ИЛИ. Диагностика в три шага занимает 10–15 минут.
Шаг 1: выпишите все роли пользователя
Откройте пользователя в списке информационной базы и посмотрите назначенные роли. Часто рядом с рабочей ролью болтается «ПравоЗапускаТонкогоКлиента», «ЧтениеОтчётов» или временно выданная административная — именно она и снимает ограничение.
Шаг 2: проверьте ограничение на спорный объект в каждой роли
Заходите в конфигуратор → каждая роль → вкладка «Ограничения доступа к данным» → нужный объект. Ищете роль, где для этого объекта:
- ограничения нет вообще (объект не в списке);
- стоит условие
ИСТИНАили пустое поле; - условие есть, но фильтрует по другому критерию, который для этого пользователя всегда выполняется.
Достаточно одной такой роли, чтобы весь фильтр обнулился — платформа берёт максимум прав.
Шаг 3: подтвердите гипотезу отключением роли
Снимите подозрительную роль у тестового пользователя, перезайдите в сеанс (параметры сеанса пересчитываются только при новом входе) и проверьте доступ. Если лишние данные исчезли — виновник найден.
Быстрый скрипт для инвентаризации всех ролей и их ограничений сразу по всем пользователям экономит время, когда база большая:
// Обработка: выгрузить пользователей и их роли
МассивПользователей = ПользователиИнформационнойБазы.ПолучитьПользователей();
Для Каждого ПользовательИБ Из МассивПользователей Цикл
ИменаРолей = "";
Для Каждого Роль Из ПользовательИБ.Роли Цикл
ИменаРолей = ИменаРолей + Роль.Роль.Имя + "; ";
КонецЦикла;
Сообщить(ПользовательИБ.Имя + " -> " + ИменаРолей);
КонецЦикла;Отдельно проверяйте эту связку после каждого обновления. Обновление типовой конфигурации нередко возвращает изменённую роль в исходное состояние или добавляет новую — и настроенный вами RLS перестаёт работать. Держите список «своих» ролей и сверяйте их шаблоны перед запуском пользователей в базу.
Читайте также: Права доступа и RLS для маркировки в 1С: 6 шагов