Тонкости проверки прав доступа

18.11.25

Администрирование - Роли и права

Когда возникает ошибка, связанная с правами доступа, не всегда понятно, куда копать… И решение проблемы может быть достаточно долгим. Знание некоторых нюансов работы платформы может помочь в этом вопросе

Итак, поехали…

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

 

 

Ошибка возникает в том случае, если в запросе выбираются данные, которые пользователю запрещены на уровне записей и в запросе не указано ключевое слово РАЗРЕШЕННЫЕ.

Если ключевое слово РАЗРЕШЕННЫЕ указать, то запрещенных записей в результате запроса не будет. А если основная таблица выборки разрешена, а запрещено одно из вложенных полей, это поле будет показано в выборки как битая ссылка, а все реквизиты этого поля будут иметь значение NULL.

Давайте посмотрим, что же меняется в запросе к серверу СУБД, в зависимости от наличия или отсутствия инструкции РАЗРЕШЕННЫЕ?

А меняется следующее:

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

CASE WHEN (EXISTS(SELECT 0x01 AS Q_001_F_000_

FROM dbo._Reference250X1 T4

INNER JOIN dbo._Reference165 T5

ON (T4._Fld59163 = ?) AND EXISTS(SELECT 0x01 AS Q_004_F_000_

FROM dbo._InfoRg47609X1 T6

WHERE ((T6._Fld2589 = ?)) AND ((T6._Fld47610_TYPE = 0x08 AND T6._Fld47610_RTRef = 0x000000FA AND T6._Fld47610_RRRef = T4._IDRRef) AND (T6._Fld47611RRef = T5._IDRRef))) AND T5._IDRRef IN

(SELECT T8._Reference165_IDRRef AS ACCESS_GROUPRRef

FROM dbo._Reference165_VT56822 T8

INNER JOIN dbo._InfoRg46624 T9

ON (T9._Fld46626_TYPE = 0x08 AND T9._Fld46626_RTRef = 0x000001F8 AND T9._Fld46626_RRRef = ?) AND (T9._Fld46625_TYPE = T8._Fld56824_TYPE AND T9._Fld46625_RTRef = T8._Fld56824_RTRef AND T9._Fld46625_RRRef = T8._Fld56824_RRRef)

WHERE ((T8._Fld2589 = ?)) AND (T9._Fld2589 = ?))

WHERE ((T5._Fld2589 = ?)) AND ((1=1) AND (CASE WHEN EXISTS(SELECT 0x01 AS Q_002_F_000_

FROM dbo._InfoRg40111 T10

WHERE ((T10._Fld2589 = ?)) AND ((T10._Fld40112RRef = T5._IDRRef) AND (T10._Fld40113_TYPE = 0x08 AND T10._Fld40113_RTRef = 0x0000018D AND T10._Fld40113_RRRef = T1._Fld20869RRef))) THEN 0x01 ELSE 0x00 END = CASE WHEN EXISTS(SELECT 0x01 AS Q_003_F_000_

FROM dbo._InfoRg40118 T11

WHERE ((T11._Fld2589 = ?)) AND ((T11._Fld40119RRef = T5._IDRRef) AND T11._Fld40120_TYPE = 0x08 AND T11._Fld40120_RTRef = 0x0000018D AND (T11._Fld40121 = 0x00))) THEN 0x01 ELSE 0x00 END)))) = 0x01 THEN 0x01 ELSE 0x00 END

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

И так, если доступ к записи разрешен, в первом поле выборки возвращается значение ИСТИНА, если не разрешен, возвращается ЛОЖЬ. После этого платформа проверяет выборку на наличие записей со значением ЛОЖЬ в первом поле. И если такие записи есть, выдает наше любимое сообщение об ошибке.

А вот если ключевое слово РАЗРЕШЕННЫЕ в запросе есть, он строиться принципиально по-другому. Все проверки выполняются не в дополнительном поле, а в секции ГДЕ. Соответственно, если проверка не проходит, запись попросту не будет возвращена, и ни каких ошибок.  

Теперь посмотрим, что меняется в запросе, если доступ на уровне записей выполняется еще и для вложенного объекта. Например, выборка из регистра «Остатки по складам». В дополнении к самому регистру есть ограничения на уровне записей к номенклатуре. Отметим, что выборке должен присутствовать какой-либо реквизит номенклатуры. Это важно, так как если в выборке присутствует только ссылка на номенклатуру, никаких дополнительных проверок выполнено не будет. Ссылка вернется запросом. А вот получение основного представления ссылки получено не будет, так как для его получения будет выполнен отдельный запрос к СУБД с дополнительной проверкой. В результате мы увидим ту самую битую ссылку.

 

Что поменяется в запросе к серверу СУБД?

Без инструкции РАЗРЕШЕННЫЕ в запросе будет дополнительная таблица, соединенная с основной левым соединением. Во второй таблице также будет дополнительное поле (ИСТИНА / ЛОЖЬ), в котором будут выполняться проверки rls уже для справочника Номенклатура. Поле это будет иметь специальный алиас: SDBL_RLS_SIGNAL_. Далее значение этого поля добавляется к первому полю основной выборки:

…AND ISNULL(T2.SDBL_RLS_SIGNAL_,0x01)

В результате мы получаем следующее поведение:

Если доступ на уровне записей к основной таблице есть, а к одному из полей нет, и в выборке есть вложенный реквизит этого поля, будет ошибка ограничения прав на уровне записей, так как в выборке будут присутствовать строки с значением первого поля = ЛОЖЬ. Если в выборке присутствует только ссылка на недоступный объект, дополнительной таблицы в запросе не будет и проверки прав на нее тоже не будет. Следовательно, не будет и ошибки, а вместо представления объекта будет показана битая ссылка.

В случае, когда в запросе есть инструкция РАЗРЕШЕННЫЕ, в запросе к СУБД также будет дополнительная таблица с левым соединением, только проверки теперь будут в секции ГДЕ этой таблицы. Соответственно, если прав к записям таблицы нет, она их просто не вернет и вложенное поле будет иметь значение NULL.

Исходя из вышеописанного можно сделать вывод, что ключевое слова РАЗРЕШЕННЫЕ влияет на поведение запроса только в случае использования rls.

Так ли это?

 

Давайте экспериментировать дальше.

Представим, что у пользователя есть доступ к основной таблице выборки и нет к вложенному объекту. Нет доступа не на уровне записей, а на уровне ролей, то есть ко всем записям таблицы.

Сформируем следующий простой запрос, без инструкции РАЗРЕШЕННЫЕ:

ВЫБРАТЬ ПЕРВЫЕ 1

ПервичныйДокумент.эу_ВПД КАК ВПД,

ПервичныйДокумент.эу_ВПД.Номер КАК ВПДНомер,

ПервичныйДокумент.Ссылка КАК Ссылка

ИЗ Документ.ПервичныйДокумент КАК ПервичныйДокумент

ГДЕ ПервичныйДокумент.Номер = &Номер

При условии, что у пользователя нет прав на уровне ролей к документу эу_ВПД, в результате мы получим ошибку:

 

 

Все очевидно и понятно. Такое же сообщение будет выведено, если запросить выборку из недоступной таблицы явно, вне зависимости от опции РАЗРЕШЕННЫЕ.

Теперь добавим инструкцию РАЗРЕШЕННЫЕ в запрос.

Опять ошибка, но сообщение следующее:

 

 

[ОшибкаВоВремяВыполненияВстроенногоЯзыка]

по причине:

{(3, 41)}: Поле не найдено "ПервичныйДокумент.эу_ВПД.Номер"

ПервичныйДокумент.эу_ВПД.Номер КАК ВПДНомер

 

Теперь изменим обращение к полю Номер используя конструкцию ВЫРАЗИТЬ

ВЫРАЗИТЬ(ПервичныйДокумент.эу_ВПД КАК Документ. эу_ВПД).Номер

Выполним запрос без конструкции РАЗРЕШЕННЫЕ.

И получаем… до боли знакомое сообщение об ошибке:

 

 

Что такое?

У нас ведь ограничение на уровне ролей, а не записей!

Ладно, давайте добавим инструкцию РАЗРЕШЕННЫЕ.

И-и-и. УСПЕХ!

Сообщения об ошибки нет. Данные возвращены. Поле ВПД представлено битой ссылкой, а поле ВПДНомер – значение NULL. Так и предполагалось.

 

Давайте разбираться.

Без конструкции ВЫРАЗИТЬ система явно показывает, что не так. В первом случае явно пишет, что к такой-то таблице нет доступа. Во-втором указывает на отсутствие реквизита объекта. Важно отметить, что в обоих случаях это проверки платформы до формирования запроса к серверу СУБД.

 

Почему поведение отличается?

Трудно сказать наверняка. Возможно, если платформа использует РАЗРЕШЕННЫЕ и встречает в запросе недоступный для пользователя объект, заменяет его на NULL. Соответственно, у поля NULL не находит нужного реквизита. В любом случае, в обоих вариантах запрос к серверу базы данных не формируется. По событию DBMSSQL в технологическом журнале вы ничего не найдете.

Если используется конструкция ВЫРАЗИТЬ, система при предварительном анализе запроса явных проблем не находит и формирует запрос к СУБД.

Без инструкции РАЗРЕШЕННЫЕ, на СУБД выполняется запрос такого вида:

SELECT TOP 1

ISNULL(T2.SDBL_RLS_SIGNAL_,0x01),

T1._Fld92959RRef,

T2.Number_,

T1._IDRRef

FROM dbo._Document1116 T1

LEFT OUTER JOIN (SELECT

(0x00) AS SDBL_RLS_SIGNAL_,

T3._Number AS Number_,

T3._IDRRef AS IDRRef,

T3._Fld2589 AS Fld2589_

FROM dbo._Document74610 T3

WHERE (T3._Fld2589 = ?)) T2

ON T1._Fld92959RRef = T2.IDRRef

WHERE ((T1._Fld2589 = ?)) AND ((T1._Number = ?))

Обратите внимание на поле: SDBL_RLS_SIGNAL_. Как видим, что поведение аналогично тому, если бы использовалось rls. Выбираются все данные и помечаются строки, в которых присутствуют запрещенные записи. В нашем случае, это все записи, в которых есть связанный объект эу_ВПД. По этой причине и сообщение об ошибке соответствующее.  

С инструкцией РАЗРЕШЕННЫЕ, запрос меняется на следующий:

SELECT TOP 1

T1._Fld92959RRef,

T2._Number,

T1._IDRRef

FROM dbo._Document1116 T1

LEFT OUTER JOIN dbo._Document74610 T2

ON ((T1._Fld92959RRef = T2._IDRRef) AND (T2._Fld2589 = ?)) AND (0x00) = 0x01

WHERE ((T1._Fld2589 = ?)) AND ((T1._Number = ?))

Обратите внимание на выражение (0x00) = 0x01. Записи дополнительной таблицы явно отсекаются. Из-за этого получаем закономерное NULL при выводе номера и никаких ошибок.

 

Какие выводы можно сделать из вышесказанного

  1. Сообщения об ошибке с явным указанием таблиц или полей свидетельствует о том, что сработал предварительный анализ запроса платформой и запрос еще не был отправлен на сервер СУБД.
  2. Конструкция РАЗРЕШЕННЫЕ в запросах, влияет на результат не только в тех случаях, когда используется rls. Соответственно сообщение «У пользователя недостаточно прав на исполнение операции над базой данных» не всегда свидетельствует об отсутствии прав на уровне записей.
  3. Совместное использование конструкций РАЗРЕШЕННЫЕ и ВЫРАЗИТЬ позволяет избежать ошибок при обращении к вложенным полям объекта, недоступного для пользователя на уровне ролей.

  

Маленький бонус

В технологическом журнале есть одно событие - QERR.

Для его включения, в файле logcfg.xml можно сделать следующую настройку:

 <log location="D:\1c\ERP" history="2">
      <event>
          <eq property="name" value="QERR"/>
          <eq property="p:processName" value="ERP "/>
      </event>                           
      <property name="all"/>
 </log>

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

В этом событии в поле Query выводится текст запроса в таком виде, в каком он был задан в конфигураторе.

Напомню, события DBMSSQL и SDBL возвращают текст запроса, преобразованный к формату базы данных.

Также в событии QERR в поле Context выводится контекст возникновения ошибки.

 

Удачи Вам в расследовании ошибок с правами доступа!

 

А с какими не очевидными ошибками системы прав доступа сталкивались Вы?

Вступайте в нашу телеграмм-группу Инфостарт

Права доступа rls БСП

См. также

Инструментарий разработчика Роли и права Запросы СКД Программист Руководитель проекта 1С:Предприятие 8 Платные (руб)

Инструменты для разработчиков 1С 8.3: Infostart Toolkit. Автоматизация и ускорение разработки на управляемых формах. Легкость работы с 1С.

16500 руб.

02.09.2020    236935    1287    419    

1104

Инструменты администратора БД Инструментарий разработчика Роли и права Программист 1С:Предприятие 8 1C:Бухгалтерия Россия Платные (руб)

Расширение позволяет без изменения кода конфигурации выполнять проверки при вводе данных, скрывать от пользователя недоступные ему данные, выполнять код в обработчиках. Не изменяет данные конфигурации, легко устанавливается практически на любую конфигурацию на управляемых формах.

17000 руб.

10.11.2023    22544    82    42    

97

Инструменты администратора БД Роли и права Системный администратор Программист Пользователь 1С 8.3 1С:Розница 2 1С:Управление нашей фирмой 1.6 1С:Документооборот 1С:Зарплата и кадры государственного учреждения 3 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Платные (руб)

Роли… Вы тратите много времени и сил на подбор ролей среди около 2400 в ERP или 1500 в Рознице 2, пытаясь понять какими правами они обладают? Вы все время смотрите права в конфигураторе или отчетах чтоб создать нормальные профили доступа? Вы хотите наглядно видеть какие права дает профиль и редактировать все в простом виде? А может хотите просто указать подсистему и дать права на просмотр и добавление на объекты и не лезть в дебри прав и чтоб обработка сама подобрала нужные роли? Все это теперь стало возможно! Обновление от 17.06.2025, версия 1.3

20400 руб.

06.12.2023    19923    71    10    

104

Логистика, склад и ТМЦ Роли и права Программист Бухгалтер Пользователь 1С:Предприятие 8 1С:Бухгалтерия 3.0 Россия Бухгалтерский учет Управленческий учет Платные (руб)

Расширение для 1С:Бухгалтерия 3.0, которое позволяет использовать отдельные роли для доступа к складским документам, для доступа к документам раздела "Производство" и для доступа к документам раздела "Покупки".

5000 руб.

21.05.2019    1699827    591    195    

145

Роли и права Системный администратор Бухгалтер Пользователь 1С:Предприятие 8 1С:Бухгалтерия 3.0 Россия Бухгалтерский учет Платные (руб)

Расширение предназначено для Бухгалтерии предприятия (версии ПРОФ и КОРП). Типовая конфигурация остается на поддержке. С помощью расширения менеджер по продажам будет иметь доступ к контрагентам и списку их документов только в случае, если он является для них ответственным. Пользователю с полными правами также доступна обработка «Назначение ответственных» для группового добавления/удаления ответственного в карточке контрагента. Есть версия данного расширения для клиентов Fresh - в магазине расширений (Fresh)

9360 руб.

14.09.2022    8319    14    6    

16

Роли и права Системный администратор Программист 1С:Предприятие 8 1С:Розница 2 1С:Управление нашей фирмой 1.6 1С:Бухгалтерия государственного учреждения 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Бухгалтерия автономного учреждения 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x 1С:Управление нашей фирмой 3.0 Платные (руб)

Мучаетесь со списком типовых ролей? Не хотите иметь дело с конфигуратором? Не знаете что делают имеющиеся права в базе? Хотите просто и удобно добавлять и настраивать, по одному клику, доступы и поведение при записи/удалении/проведении/открытии списка/фильтрацию данных в списках или формах выбора для пользователя или группы пользователей и для любого объекта? Не хотите переживать, что при обновлении конфигурации все права и роли слетят? (Обновление от 28.08.2025, версия 1.10)

18000 руб.

21.03.2022    18480    28    55    

51

Ценообразование, анализ цен Роли и права Системный администратор 1С:Предприятие 8 1С:Управление нашей фирмой 1.6 1С:Управление нашей фирмой 3.0 Россия Платные (руб)

Расширение возможностей программы 1С:УНФ 1.6 и 3.0. Функционал расширения - разграничение всевозможных прав пользователей и контроль при совершении различных действий.

5016 руб.

23.02.2018    65405    178    264    

169
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. RustIG 1934 18.11.25 10:55 Сейчас в теме
А с какими не очевидными ошибками системы прав доступа сталкивались Вы?

механизм ЭДО - все процедуры в фоновом режиме через механизм длительных операций - Журнал регистрации плохо фиксирует любые ошибки (в том числе, нарушение прав доступа) - выдает ошибку в модуле длительной операции, а какой процесс в него попал неизвестно.... Естественно, через отладчик в этот модуль не попасть, а если отлаживать не в фоновом режиме (в ручном режиме), то в модуль длительных сеансов не попасть.... если повезет всплывет ошибка...
ids79; adhocprog; +2 Ответить
2. RustIG 1934 18.11.25 11:09 Сейчас в теме
а как такие ограничения отлаживать? запускать консоль запросов под пользователем с ограниченными правами? и проверять запросы в окне консоли? получится ли так? или только через отладчик и конфигуратор? или и вовсе только через технологический журнал?
3. ids79 8772 18.11.25 11:46 Сейчас в теме
(2) В этом случае наверно только через технологический журнал
4. ixijixi 2088 20.11.25 08:43 Сейчас в теме
(2) Для отладки RLS есть вот такая консоль и такая подсистема. Сам правда не юзал)
ids79; RustIG; +2 Ответить
9. triviumfan 102 24.11.25 14:29 Сейчас в теме
(4) Оба решения-динозавры, давно не поддерживаются и нерабочие)
5. ccapt 20.11.25 12:07 Сейчас в теме
Как и многое другое в решениях 1С, непонятно, почему поведение "только разрешенные" не является поведением по умолчанию, если не указано обратное. Трудности выражения инструкции игнорирования RLS одним словом? Хинты?
6. ids79 8772 20.11.25 12:23 Сейчас в теме
(5) Согласен. Поведение "по умолчанию" должно быть "только разрешенные".
Ошибок было бы значительно меньше.
Для чего может понадобиться формирование запроса без инструкции РАЗРЕШЕННЫЕ...
Возможно, только чтобы отследить, не попадают ли в выборку данные, которых не должно быть по отборам.
И наверно все.
7. maxx 1000 20.11.25 13:19 Сейчас в теме
А еще интересная тема, с которой сталкивался на PostgreSQL, это безумнейшая разница во времени выполнения запроса под пользователями с правами RLS с и без слова Разрешенные. Например, если в запросе уже стоит отбор , по которому не попадают уже запрещенные для пользователя записи, то такой запрос со словом Разрешенные может уходить на несколько часов подумать, а без Разрешенные делается за несколько секунд.
ids79; nvv1970; +2 Ответить
8. tormozit 7329 21.11.25 07:00 Сейчас в теме
(0) Помогу автору форматировать текст запроса через ИР. Сайт зачем то сам вставляет пробелы внутрь слов SEL ECT и FR OM (видимо какая то защита от взлома). Поэтому вложил текстом отформатированный оригинал.
CASE
	WHEN (EXISTS (
	SEL ECT
		0x01 AS Q_001_F_000_
	FR OM
		dbo._Reference250X1 AS T4
		INNER JOIN dbo._Reference165 AS T5
		ON 0 = 0
			AND T4._Fld59163 = ?
			AND EXISTS (
				SEL ECT
					0x01 AS Q_004_F_000_
				FR OM
					dbo._InfoRg47609X1 AS T6
				WHERE 0 = 0
					AND T6._Fld2589 = ?
					AND T6._Fld47610_TYPE = 0x08
					AND T6._Fld47610_RTRef = 0x000000FA
					AND T6._Fld47610_RRRef = T4._IDRRef
					AND T6._Fld47611RRef = T5._IDRRef)
			AND T5._IDRRef IN (
				SEL ECT
					T8._Reference165_IDRRef AS ACCESS_GROUPRRef
				FR OM
					dbo._Reference165_VT56822 AS T8
					INNER JOIN dbo._InfoRg46624 AS T9
					ON 0 = 0
						AND T9._Fld46626_TYPE = 0x08
						AND T9._Fld46626_RTRef = 0x000001F8
						AND T9._Fld46626_RRRef = ?
						AND T9._Fld46625_TYPE = T8._Fld56824_TYPE
						AND T9._Fld46625_RTRef = T8._Fld56824_RTRef
						AND T9._Fld46625_RRRef = T8._Fld56824_RRRef
				WHERE 0 = 0
					AND T8._Fld2589 = ?
					AND T9._Fld2589 = ?)
	WHERE 0 = 0
		AND T5._Fld2589 = ?
		AND 1 = 1
		AND CASE
			WHEN EXISTS (
			SELECT
				0x01 AS Q_002_F_000_
			FR OM
				dbo._InfoRg40111 AS T10
			WH ERE 0 = 0
				AND T10._Fld2589 = ?
				AND T10._Fld40112RRef = T5._IDRRef
				AND T10._Fld40113_TYPE = 0x08
				AND T10._Fld40113_RTRef = 0x0000018D
				AND T10._Fld40113_RRRef = T1._Fld20869RRef)
				THEN 0x01
			ELSE 0x00
		END = CASE
			WHEN EXISTS (
			SELECT
				0x01 AS Q_003_F_000_
			FR OM
				dbo._InfoRg40118 AS T11
			WH ERE 0 = 0
				AND T11._Fld2589 = ?
				AND T11._Fld40119RRef = T5._IDRRef
				AND T11._Fld40120_TYPE = 0x08
				AND T11._Fld40120_RTRef = 0x0000018D
				AND T11._Fld40121 = 0x00)
				THEN 0x01
			ELSE 0x00
		END)) = 0x01
		THEN 0x01
	ELSE 0x00
END
Показать
Прикрепленные файлы:
Clip_783845.txt
10. ids79 8772 25.11.25 16:45 Сейчас в теме
(8) Спасибо Сергей. Когда отформатировано, красивей выгладит, но слишком громоздко получается. Лично для меня даже как-то хуже читается. Но это видимо, кому как привычнее.
Для отправки сообщения требуется регистрация/авторизация