Способы определить привилегированный режим: код, отладчик, журналы
Содержание
Самый быстрый способ — вызвать в коде функцию ПривилегированныйРежим(). Она вернёт Истина, если текущий участок исполняется с отключённой проверкой прав и без ограничений доступа на уровне записей (RLS). Функция доступна на сервере, в фоновом задании и во внешнем соединении.
Но спрашивают об этом по-разному. Иногда нужно убедиться прямо из своей процедуры, иногда — выяснить, почему пользователь без прав увидел «чужие» данные, а иногда — разобраться, в каком режиме отработал проблемный участок типовой конфигурации. Под каждую задачу — свой инструмент: встроенная функция, отладчик, технологический журнал, анализ ролей.
Ниже — платформа 1С:Предприятие 8.3 (интерфейс «Такси»), клиент-серверный и файловый варианты. Привилегированный режим — механизм серверный, поэтому большая часть проверок выполняется на стороне сервера.
Что отключает привилегированный режим и зачем его контролировать
Привилегированный режим — это участок кода, внутри которого платформа не проверяет права пользователя и не применяет ограничения доступа к данным (RLS). Код обращается к любым объектам так, будто у текущего пользователя полные права.
Его включают осознанно: служебные операции (запись регистров, проведение, доступ к справочникам настроек), которые пользователь по правам делать не должен, но которые нужны в рамках бизнес-логики. Проблема возникает, когда режим включили и забыли выключить или включили шире, чем нужно, — тогда пользователь получает доступ к данным, которые от него закрыты.
Чтобы понять эффект, представьте типичное ограничение RLS: менеджер видит документы только своей организации — остальные скрыты условием в роли. Пока код идёт обычно, платформа подставляет это условие в каждый запрос к документам. Как только участок входит в привилегированный режим, условие перестаёт действовать, и тот же запрос вернёт документы всех организаций. Именно поэтому важно знать, в каком режиме отработал конкретный блок: от этого зависит, что увидел пользователь.
Поэтому проверять режим приходится в двух ситуациях:
- 🔍 разработка — убедиться, что служебный блок идёт привилегированно, а пользовательский — нет;
- 🛡️ разбор инцидента — понять, почему проверка прав не сработала и где код «поднял» себе полномочия.
Включается режим вызовом УстановитьПривилегированныйРежим(Истина), выключается — УстановитьПривилегированныйРежим(Ложь). Эти вызовы вложенные: сколько раз включили, столько же нужно выключить.
Функция ПривилегированныйРежим() — проверка прямо в коде
Базовый инструмент — две встроенные функции глобального контекста.
ПривилегированныйРежим() возвращает булево: Истина — код сейчас в привилегированном режиме, Ложь — в обычном. Параметров нет.
Если ПривилегированныйРежим() Тогда
Сообщить("Код идёт привилегированно: права и RLS отключены");
Иначе
Сообщить("Обычный режим: проверка прав действует");
КонецЕсли;
КоличествоПривилегированныхРежимов() возвращает число — сколько раз режим включался вложенно и ещё не выключен. Ноль означает обычный режим, значение больше нуля — глубину вложенности. Это удобно, когда нужно убедиться, что включений и выключений поровну.
Сообщить(СтрШаблон("Глубина привилегированного режима: %1",
КоличествоПривилегированныхРежимов()));
Чтобы не словить «протекший» режим из-за исключения, включение и выключение оборачивают в Попытка … КонецПопытки:
УстановитьПривилегированныйРежим(Истина);
Попытка
// служебные операции без проверки прав
ЗаписатьСлужебныеДанные();
Исключение
УстановитьПривилегированныйРежим(Ложь);
ВызватьИсключение;
КонецПопытки;
УстановитьПривилегированныйРежим(Ложь);
УстановитьПривилегированныйРежим() работает только на сервере и во внешнем соединении. На тонком и веб-клиенте этот вызов недоступен и приведёт к ошибке компиляции. А вот ПривилегированныйРежим() вызвать можно где угодно — на клиенте она просто вернёт Ложь.
Если нужно разово «подсветить» режим в чужом коде, не меняя логику, добавьте временную строку с записью в журнал регистрации — к ней вернёмся ниже.
Проверка в отладчике без правки кода
Когда менять конфигурацию нельзя, а понять режим в конкретной точке надо, помогает отладчик конфигуратора.
Порядок действий для клиент-серверной базы:
- В конфигураторе откройте
Отладка → Подключениеи подключитесь к серверному предмету отладки (нужно, чтобы на сервере был разрешён отладчик — параметр задаётся при запуске службы кластера). - Поставьте точку останова (
F9) на нужной строке модуля. - Выполните в базе действие, которое приводит к этой строке. Отладчик остановится.
- Нажмите
Shift+F9(Вычислить выражение) и введитеПривилегированныйРежим(). В поле результата увидитеИстинаилиЛожь.
Тот же результат можно держать перед глазами постоянно: добавьте ПривилегированныйРежим() и КоличествоПривилегированныхРежимов() в окно Табло — значения будут пересчитываться на каждом шаге отладки.
Отладчик отвечает на вопрос «в каком режиме строка исполняется сейчас», а не «включался ли режим когда-то». Чтобы увидеть момент включения, ставьте точку останова прямо на строку УстановитьПривилегированныйРежим(Истина) в подозрительном модуле.
Для файловой базы отладка проще — предмет отладки один (клиент), подключение к серверу не требуется, остальные шаги те же.
Если точка останова не срабатывает на сервере, проверьте, что отладка по протоколу разрешена при запуске агента сервера, а в свойствах информационной базы кластера блокировка регламентных заданий и сеансов не мешает запуску. Без разрешённой серверной отладки вычислить ПривилегированныйРежим() на сервере не получится — останется только путь с логированием в код.
Привилегированные общие модули и роли
Режим включается не только явным вызовом. У общего модуля есть свойство Привилегированный: если оно установлено, все экспортные процедуры и функции этого модуля выполняются привилегированно без единой строки УстановитьПривилегированныйРежим.
Поэтому первый шаг при разборе — открыть в конфигураторе свойства общего модуля, через который прошёл вызов, и посмотреть флаг Привилегированный. Если он стоит — весь код модуля идёт с отключёнными правами, и ПривилегированныйРежим() внутри него вернёт Истина.
Как режим связан с ролевой моделью:
- роли задают права (чтение, добавление, проведение) и ограничения доступа к данным (RLS) — именно их привилегированный режим и обходит;
- RLS применяется ко всем пользователям, у которых назначена роль с ограничениями, — и обычным, и с широкими правами; снимает его только привилегированный режим;
- обход через режим — это не повышение прав конкретного пользователя, а доверие к коду разработчика. Пользователь выполняет написанную процедуру, а не получает новые полномочия интерактивно.
Флаг Привилегированный у общего модуля действует на сервере. Клиентские процедуры этого модуля привилегированными не становятся — на клиенте механизма просто нет.
Отсюда практический вывод: если пользователь без прав видит закрытые данные, ищите либо явный УстановитьПривилегированныйРежим(Истина), либо привилегированный общий модуль в цепочке вызова.
Отдельно стоит внешнее соединение (COM-подключение к базе): код в нём, как и на сервере, может переключать режим, и ПривилегированныйРежим() там тоже работает. Это важно при разборе интеграций: обработка, подключающаяся к базе внешним соединением, способна войти в привилегированный режим так же, как серверный код.
Фоновые и регламентные задания: где смотреть режим
Код фонового задания исполняется на сервере, поэтому там доступны обе функции и можно вызвать УстановитьПривилегированныйРежим. Само по себе задание привилегированным не становится — оно работает с правами того пользователя, под которым запущено (для регламентного задания этот пользователь задаётся в его настройках).
Проверить режим внутри задания интерактивным отладчиком неудобно — выполнение идёт без пользователя. Надёжнее — логирование в журнал регистрации из самого кода задания:
ЗаписьЖурналаРегистрации(
"ПроверкаРежима",
УровеньЖурналаРегистрации.Информация,
,
,
СтрШаблон("Привилегированный режим: %1, глубина: %2",
ПривилегированныйРежим(),
КоличествоПривилегированныхРежимов()));
После запуска задания откройте журнал и отфильтруйте записи по комментарию — увидите фактический режим на момент выполнения. Для долгих заданий такие метки ставят в начале и в конце ключевых блоков.
Отладить фоновое задание можно и напрямую: в настройках отладки конфигуратора включите остановку в фоновых заданиях, тогда точки останова сработают и в их коде.
Журналы сервера: где искать следы режима
Технологический журнал не хранит отдельного признака «привилегированный режим» — такого поля в нём нет. Его роль другая: показать, какой модуль и метод отработал и в какой последовательности шли вызовы. Зная цепочку, вы находите подозрительный участок, а сам режим подтверждаете уже в коде или отладчике.
Журнал включается файлом logcfg.xml в каталоге conf рабочего процесса. Полезны события серверных вызовов и исключений — по ним видно имена модулей и методов в стеке. Дальше открываете найденный общий модуль и смотрите флаг Привилегированный или ищете в нём явное включение режима.
Дампы памяти (события аварийных завершений) к проверке режима прямого отношения не имеют — они нужны, когда процесс падает, а не когда надо выяснить права. Включать полную трассировку техжурнала на нагруженной базе постоянно не стоит: файлы растут быстро и дают заметную нагрузку. Включили для диагностики — выключите после.
Журнал регистрации тоже не содержит колонки «режим». Но он помогает выявить последствия привилегированного режима: если пользователь выполнил действие, которого по своим правам делать не может (например, запись в закрытый от него регистр), значит, код в этот момент шёл привилегированно.
Как использовать:
- отфильтруйте журнал по пользователю и периоду инцидента (
Администрирование → Журнал регистрацииили аналогичный раздел конфигурации, плюс фильтр по пользователю); - сопоставьте выполненные действия с его ролями: расхождение указывает на привилегированный код в цепочке;
- для точной фиксации добавьте в подозрительный код запись в журнал через
ЗаписьЖурналаРегистрации()с текущим значениемПривилегированныйРежим(), как в примере выше; - если инцидент разовый и воспроизвести его тяжело, выгрузите журнал за нужный интервал в файл и анализируйте выгрузку отдельно, не нагружая рабочую базу фильтрацией большого периода.
Этого достаточно, чтобы от «что-то пошло не так» перейти к конкретному модулю. Дальше в конфигураторе остаётся открыть этот модуль и проверить две вещи: свойство Привилегированный у общего модуля и наличие явных переключений режима в теле метода. Так косвенный след из журнала превращается в точный ответ, в каком режиме шёл код.
Если нужно разобрать повторяющийся инцидент, оставьте запись в журнал на постоянной основе только в конкретном методе, а не по всей цепочке: лишние записи раздувают журнал и усложняют поиск.
Какой способ выбрать
ПривилегированныйРежим() прямо в код. Нужна глубина вложенности — добавьте КоличествоПривилегированныхРежимов().ПривилегированныйРежим() через Shift+F9 или окно «Табло».УстановитьПривилегированныйРежим(Истина); последствия сверьте по журналу регистрации.ПривилегированныйРежим() в журнал регистрации из кода задания — отладка без пользователя неудобна.Частые ошибки при работе с привилегированным режимом
- Включили режим и не выключили. Без пары
УстановитьПривилегированныйРежим(Ложь)весь дальнейший код в этом вызове идёт с отключёнными правами. Контролируйте баланс черезКоличествоПривилегированныхРежимов()— после вашего блока она должна вернуться к исходному значению. - Режим «протёк» через исключение. Если между включением и выключением возникла ошибка, выключение не выполнится. Оборачивайте блок в
Попытка … КонецПопыткии выключайте режим в секцииИсключение. - Ждут привилегированности на клиенте. Флаг общего модуля и
УстановитьПривилегированныйРежимработают на сервере. Клиентский код привилегированным не становится. - Путают режим с полными правами. Пользователь с полными правами всё равно под действием RLS своих ролей, пока код не вошёл в привилегированный режим. Это разные механизмы.
- Ищут режим в журналах напрямую. Ни журнал регистрации, ни технологический журнал не помечают привилегированный режим отдельным флагом. Они указывают на код, а режим подтверждается функцией или отладчиком.
Частые вопросы
Чем `ПривилегированныйРежим()` отличается от `УстановитьПривилегированныйРежим()`?
Истина — включить, Ложь — выключить. Переключение доступно лишь на сервере и во внешнем соединении.Можно ли проверить режим на клиенте?
ПривилегированныйРежим() на клиенте можно, но она вернёт Ложь: клиентский код привилегированным не бывает. Включить режим на клиенте нельзя.