Производительный вариант RLS в БСП (в коде — универсальное ограничение доступа на уровне записей) работает через ключи доступа. Для каждого ограничиваемого объекта БСП заранее вычисляет ключ — уникальное сочетание значений доступа, например «организация + склад», — и хранит связи «объект → ключ» и «ключ → набор групп доступа или пользователь». Шаблон ограничения в роли (#ДляОбъекта, #ДляРегистра) при этом не проверяет реквизиты объекта, а просто ищет, есть ли у текущего пользователя связь с ключом объекта. Если связи нет — запись не видна.

Отсюда и знаменитое «ключи не пересчитались»: если фоновое обновление ключей и связей отстало или упало, пользователь видит не то, что разрешено настройками. В статье разберём, какие параметры сеанса и регистры участвуют в проверке, как устроен шаблон и как вручную получить запрос ограничения, чтобы найти причину проблемы с доступом. Имена объектов приведены по актуальным версиям БСП 3.x — в вашей версии они могут немного отличаться.

Где описываются ограничения в производительном варианте

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

1С
// См. УправлениеДоступомПереопределяемый.ПриЗаполненииСписковСОграничениемДоступа.
Процедура ПриЗаполненииОграниченияДоступа(Ограничение) Экспорт

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

КонецПроцедуры

А в роли для таблицы указывается стандартный шаблон, скопированный из эталонной роли БСП без изменений (в документации подсистемы рекомендуется брать шаблоны из роли ИзменениеУчастниковГруппДоступа):

1С
#ДляОбъекта("")

Объект также регистрируется в УправлениеДоступомПереопределяемый.ПриЗаполненииСписковСОграничениемДоступа. Подробный порядок подключения нового объекта — отдельная тема; здесь нас интересует, что происходит при чтении.

Участники: параметры сеанса

При входе пользователя БСП вычисляет параметры сеанса, которые затем подставляются в шаблоны:

Параметр сеансаТипСмысл
ОграничениеДоступаНаУровнеЗаписейУниверсальноБулевоВключён ли производительный вариант
СпискиСОтключеннымОграничениемЧтенияСтрокаТаблицы, для которых у пользователя ограничение не действует; Все — ограничений нет вообще
СпискиСОграничениемЧерезКлючиДоступаГруппДоступаСтрокаТаблицы, проверяемые через ключи групп доступа, с вариантами проверки в суффиксах
СпискиСОграничениемЧерезКлючиДоступаПользователейСтрокаТаблицы, где в ограничении участвует сам пользователь
РазрешенныйНаборГруппДоступаСправочник НаборыГруппДоступаСочетание групп доступа, в которые входит пользователь
РазрешенныйПустойНаборГруппДоступаСправочник НаборыГруппДоступаСлужебный набор для ключей, разрешённых всем
РазрешенныйПользовательСправочник НаборыГруппДоступаНабор, связывающий пользователя с его разрешёнными ключами
ТекущийВнешнийПользовательСправочник ВнешниеПользователиВнешний пользователь сеанса или пустая ссылка

Суффиксы в строках списков кодируют вариант проверки. Например, отметка ;0 у таблицы означает, что у пользователя нет ни одной роли с правом чтения — таблица недоступна целиком, и ключи даже не проверяются.

Участники: справочники и регистры

ОбъектЧто хранит
Справочник КлючиДоступаУникальные сочетания значений доступа для вида объектов. Два ограничивающих поля — по ключу на каждую встречающуюся пару значений
Справочник НаборыГруппДоступаСочетания групп доступа и связь пользователя с разрешённым сочетанием
РС КлючиДоступаКОбъектамКакой ключ у каждого объекта ссылочного типа (отдельно для пользователей и внешних пользователей)
РС КлючиДоступаКРегистрамТо же для регистров
РС КлючиДоступаНаборовГруппДоступаКакие ключи разрешены каким наборам групп. Запись есть, только если хотя бы одна группа набора даёт доступ к ключу
РС КлючиДоступаПользователей / КлючиДоступаВнешнихПользователейРазрешённые ключи для конкретного пользователя
Производительный вариант RLS: объект связан с ключом, ключ — с набором групп, набор — с пользователем
Производительный вариант RLS: объект связан с ключом, ключ — с набором групп, набор — с пользователем

Цепочка проверки: объект → ключ доступа → набор групп (или пользователь) → текущий сеанс. Количество ключей зависит от количества уникальных сочетаний значений, а не от количества объектов. Поэтому при проектировании ограничений важно, чтобы сочетаний было как можно меньше: ограничение по пяти полям с высокой вариативностью порождает огромное число ключей и долгие пересчёты.

Как устроен шаблон ДляОбъекта

Шаблон — это текст ограничения с командами препроцессора #Если, #ИначеЕсли, #Иначе, #КонецЕсли. При обращении к таблице платформа подставляет параметры сеанса, вычисляет условия и оставляет только подходящие ветки. В результате получается обычное условие запроса, которое даёт ИСТИНА или ЛОЖЬ для каждой записи.

Логика шаблона по шагам (упрощённо):

  1. База заблокирована для обновления (СпискиСОтключеннымОграничениемЧтения = "Неопределено") — ГДЕ ЛОЖЬ, недоступно ничего.
  2. Ограничений нет вообще (= "Все") — ГДЕ ИСТИНА.
  3. Для текущей таблицы ограничение отключено (имя таблицы есть в списке отключённых) — ГДЕ ИСТИНА.
  4. Таблица недоступна целиком (суффикс ;0) — ГДЕ ЛОЖЬ.
  5. Таблица не найдена ни в одном списке — ошибка «Требуется актуализировать ограничение доступа». Обычно это значит, что объект не подключён к механизму или параметры сеанса устарели.
  6. Иначе — проверка через ключи. Это основная ветка: подзапрос к КлючиДоступаКОбъектам с левыми соединениями к регистрам разрешённых ключей.

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

Запрос 1С
ТекущаяТаблица ГДЕ ИСТИНА В
	(ВЫБРАТЬ ПЕРВЫЕ 1
		ИСТИНА
	ИЗ
		РегистрСведений.КлючиДоступаКОбъектам КАК КлючиОбъектов
			ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КлючиДоступаНаборовГруппДоступа КАК КлючиНабора
			ПО КлючиНабора.КлючДоступа = КлючиОбъектов.КлючДоступаПользователей
				И КлючиНабора.НаборГруппДоступа = &РазрешенныйНаборГруппДоступа
			ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КлючиДоступаНаборовГруппДоступа КАК КлючиДляВсех
			ПО КлючиДляВсех.КлючДоступа = КлючиОбъектов.КлючДоступаПользователей
				И КлючиДляВсех.НаборГруппДоступа = &РазрешенныйПустойНаборГруппДоступа
			ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КлючиДоступаПользователей КАК КлючиПользователя
			ПО КлючиПользователя.КлючДоступа = КлючиОбъектов.КлючДоступаПользователей
				И КлючиПользователя.Пользователь = &РазрешенныйПользователь
	ГДЕ
		КлючиОбъектов.Объект = ТекущаяТаблица.Ссылка
		И (НЕ КлючиНабора.КлючДоступа ЕСТЬ NULL
			ИЛИ НЕ КлючиДляВсех.КлючДоступа ЕСТЬ NULL
			ИЛИ НЕ КлючиПользователя.КлючДоступа ЕСТЬ NULL))

Смысл: найти ключ объекта и проверить, что он разрешён хотя бы одним из способов. Все соединения — по индексированным полям небольших регистров, поэтому такая проверка работает быстро даже на больших таблицах.

Параметр ПолеОбъекта

Шаблон принимает параметр #ПолеОбъекта. Если он пустой — соединение идёт по ТекущаяТаблица.Ссылка. Если передано имя поля, соединение идёт по нему: так ограничиваются, например, табличные части или подчинённые справочники через владельца, когда в ПриЗаполненииОграниченияДоступа используется ЧтениеОбъектаРазрешено(Владелец).

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

Алгоритм, которым я пользуюсь при разборе обращений «не вижу документ» или «вижу чужое»:

  1. Откройте сеанс под проблемным пользователем (в отладке) и посмотрите значения параметров сеанса — например, внешней обработкой, которая выводит их на форму.
  2. СпискиСОтключеннымОграничениемЧтения. Если там Все — у пользователя полные права или RLS не включён. Если в списке есть нужная таблица — какая-то роль даёт на неё полный доступ.
  3. СпискиСОграничениемЧерезКлючиДоступаГруппДоступа. Нет таблицы — объект не подключён к механизму. Есть с ;0 — у пользователя нет ролей с чтением этой таблицы.
  4. Соберите итоговый запрос. Возьмите текст шаблона из роли, вычеркните ветки препроцессора, не подходящие под параметры сеанса, и замените первую строку на выборку:
Запрос 1С
ВЫБРАТЬ
	ТекущаяТаблица.Ссылка
ИЗ
	Документ.ЗаказКлиента КАК ТекущаяТаблица
ГДЕ
	ИСТИНА В
		(ВЫБРАТЬ ПЕРВЫЕ 1 ИСТИНА ...)
  1. Выполните запрос в консоли под полными правами с параметрами из сеанса пользователя. Если нужного документа нет в результате — смотрите по цепочке: есть ли запись в КлючиДоступаКОбъектам, есть ли этот ключ в КлючиДоступаНаборовГруппДоступа для набора пользователя.

Типичные находки:

  • нет записи в КлючиДоступаКОбъектам — ключ для объекта ещё не рассчитан (документ только что создан или изменены поля ограничения);
  • ключ есть, но нет связи с набором групп — не обновлены связи после изменения состава групп или настроек видов доступа;
  • связь есть, документ не виден — проблема в другой роли или в другом праве (например, проверяется право изменения, а не чтения).

Типичные ошибки и как их избежать

  • Правка шаблонов в ролях. В производительном варианте шаблоны общие, правка ломает логику и усложняет обновление. Меняйте ПриЗаполненииОграниченияДоступа.
  • Слишком много ограничивающих полей. Количество ключей растёт как произведение вариантов значений. Ограничивайте по тем полям, которые реально нужны бизнесу.
  • Массовая загрузка данных и сразу проверка доступа. Ключи досчитываются фоном; пока обновление не завершено, результат проверки ненадёжен.
  • Остановленное регламентное задание обновления доступа. Без него ключи и связи перестают обновляться, а проблемы проявляются через дни.
  • Отладка под администратором. У полноправного пользователя ограничений нет, и проблема не воспроизводится. Всегда проверяйте под конкретным пользователем.
RLS в производительном варианте не «магия»: это три связи — объект с ключом, ключ с набором групп, набор с пользователем. Найдите, какая из них отсутствует, и вы найдёте причину.

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

Итог

  • Производительный вариант RLS проверяет не реквизиты объекта, а наличие связи ключа доступа объекта с набором групп или пользователем.
  • Ограничения описываются в ПриЗаполненииОграниченияДоступа модуля менеджера; шаблоны ролей копируются без изменений.
  • Параметры сеанса определяют, какие ветки шаблона попадут в итоговый запрос.
  • Для диагностики соберите запрос из шаблона по параметрам сеанса пользователя и выполните его под полными правами.
  • Держите число ключей минимальным и следите за фоновым обновлением доступа.