Как устранить ошибку «Нарушение прав доступа» при работе с Хранилищем общих настроек в 1С?

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

При разработке и кастомизации конфигураций на платформе «1С:Предприятие 8.3» программисты часто сталкиваются со стандартным системным механизмом сохранения пользовательских настроек. Одним из наиболее удобных инструментов для этого является объект ХранилищеОбщихНастроек. Однако при попытке прочитать или записать настройки программным путем под пользователем с ограниченными правами нередко возникает критическая ошибка: «Нарушение прав доступа».

В этой статье мы подробно разберем, почему возникает данная проблема, как устроен механизм безопасности платформы при работе с настройками, и рассмотрим несколько эффективных способов решения этой задачи в различных сценариях.

Выясняем причину: почему возникает ошибка нарушения прав доступа?

Типичный сценарий возникновения ошибки выглядит следующим образом. Разработчик пытается загрузить настройки с помощью следующей строки кода:


Настройки = ХранилищеОбщихНастроек.Загрузить(КлючОбъекта, КлючНастроек, ОписаниеНастроек, ИмяПользователя);

Если этот код выполняется под пользователем с полными правами, все отрабатывает корректно. Но как только код запускает обычный пользователь, система выдает ошибку доступа. Обратимся к синтакс-помощнику платформы «1С:Предприятие».

Согласно документации, если в методе Загрузить параметр ИмяПользователя указывает на пользователя, отличного от текущего (то есть мы пытаемся прочитать чужие настройки), либо если мы пытаемся прочитать общие настройки без указания конкретного пользователя, платформе требуется наличие у текущего сеанса специального административного права — «Администрирование данных» (Data administration).

По умолчанию это право есть только у администраторов системы (пользователей с полными правами). Обычным пользователям давать такое право из соображений безопасности категорически не рекомендуется.

Почему не работает УстановитьПривилегированныйРежим() на клиенте?

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


УстановитьПривилегированныйРежим(Истина);
Настройки = ХранилищеОбщихНастроек.Загрузить(КлючОбъекта, КлючНастроек, , ИмяПользователя);
УстановитьПривилегированныйРежим(Ложь);

На локальной файловой базе такой код может успешно сработать. Однако при переходе на клиент-серверный вариант (SQL-базу) этот прием перестает работать, и программа снова выбрасывает ошибку доступа. Выясним причину этого поведения.

Дело в том, что в клиент-серверном варианте вызов метода УстановитьПривилегированныйРежим(Истина) на стороне клиента полностью игнорируется платформой. Привилегированный режим может быть установлен и реально функционирует исключительно на стороне сервера.

Ниже мы разберем по шагам правильные и безопасные способы обхода этой проблемы.

Решение 1. Вынос чтения настроек на сервер в привилегированный модуль

Это самый правильный, безопасный и стандартный способ решения проблемы. Нам необходимо спроектировать логику так, чтобы обращение к ХранилищеОбщихНастроек происходило на стороне сервера в контексте, где проверки прав платформы можно временно отключить.

Выполним следующие действия по шагам:

  1. Создадим в конфигураторе новый общий модуль (или используем существующий, предназначенный для серверных функций). Назовем его, например, РаботаСНастройкамиСервер.
  2. В свойствах этого общего модуля обязательно установим флаги «Сервер» и «Привилегированный». Флаг «Привилегированный» означает, что все процедуры и функции этого модуля будут выполняться на сервере без проверки прав доступа (с правами системного администратора).
  3. Напишем внутри модуля экспортную функцию для загрузки настроек:

// Функция считывает настройки любого пользователя без проверки прав доступа сеанса
Функция ПолучитьНастройкиПользователя(Знач КлючОбъекта, Знач КлючНастроек, Знач ИмяПользователя = "") Экспорт
    
    ОписаниеНастроек = Неопределено;
    Возврат ХранилищеОбщихНастроек.Загрузить(КлючОбъекта, КлючНастроек, ОписаниеНастроек, ИмяПользователя);
    
КонецФункции

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

Если же мы не хотим делать весь модуль привилегированным, мы можем использовать стандартный серверный модуль и прописать управление режимом вручную:


Функция ПолучитьНастройкиПользователяБезопасно(Знач КлючОбъекта, Знач КлючНастроек, Знач ИмяПользователя = "") Экспорт
    
    УстановитьПривилегированныйРежим(Истина);
    ОписаниеНастроек = Неопределено;
    Результат = ХранилищеОбщихНастроек.Загрузить(КлючОбъекта, КлючНастроек, ОписаниеНастроек, ИмяПользователя);
    УстановитьПривилегированныйРежим(Ложь);
    
    Возврат Результат;
    
КонецФункции

Теперь на стороне клиента мы можем легко вызвать нашу серверную функцию, и никакой ошибки нарушения прав доступа не возникнет.

Решение 2. Использование «фейкового» пользователя для хранения глобальных настроек

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

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

Посмотрим на пример записи такой настройки:


// Записываем общие настройки интеграции под виртуальным пользователем
ХранилищеОбщихНастроек.Сохранить("ПараметрыИнтеграции", "НастройкиПодключения", СтруктураПараметров, , "#ГлобальныеНастройки");

Поскольку этот виртуальный пользователь гарантированно отличается от текущего авторизованного пользователя, для чтения этой настройки обычным пользователям также понадобится обертка в виде серверного привилегированного модуля, описанная в Решении 1. Данный подход позволяет элегантно изолировать глобальные настройки системы от индивидуальных настроек пользователей.

Решение 3. Предоставление роли права «Администрирование данных»

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

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

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

Решение 4. Использование стандартных механизмов БСП (Библиотеки стандартных подсистем)

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

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


// Загрузка настроек с помощью БСП
Настройки = ОбщегоНазначения.ХранилищеОбщихНастроекЗагрузить(КлючОбъекта, КлючНастроек, , ИмяПользователя);

// Сохранение настроек с помощью БСП
ОбщегоНазначения.ХранилищеОбщихНастроекСохранить(КлючОбъекта, КлючНастроек, ЗначениеНастроек, , ИмяПользователя);

Использование функций БСП имеет ряд неоспоримых преимуществ перед прямым обращением к платформенному менеджеру настроек:

Решение 5. Создание собственного Хранилища настроек

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

В этом случае оптимальным решением будет создание собственного объекта метаданных. Разберем этот процесс:

  1. В дереве метаданных конфигуратора перейдите в ветку «Общие» -> «Хранилища настроек».
  2. Добавьте новый объект метаданных и назовите его, например, НашеХранилищеНастроек.
  3. В свойствах конфигурации (кликните правой кнопкой мыши по корню конфигурации, выберите «Свойства») найдите свойство «Хранилище общих настроек» и укажите там созданный объект НашеХранилищеНастроек.
  4. Откройте модуль менеджера вашего хранилища настроек. Там вы можете переопределить стандартные процедуры платформы:
    • ПриСохранении — вызывается при записи настроек.
    • ПриЗагрузке — вызывается при чтении настроек.
    • ПриВыборе — вызывается при интерактивном выборе настроек пользователем.

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

Подведем итог: наиболее частой ошибкой при работе с ХранилищеОбщихНастроек является попытка включить привилегированный режим на стороне клиента в клиент-серверной базе. Перенос кода на сервер в привилегированный общий модуль или использование стандартных функций БСП полностью решает эту проблему без ущерба для безопасности системы.

← На главную