Как исправить ошибку «Нарушение прав доступа!» при формировании отчета на СКД?

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

Приветствуем вас, уважаемые коллеги! Сегодня мы детально разберем одну крайне интересную и неочевидную проблему, с которой часто сталкиваются разработчики и администраторы систем на платформе 1С:Предприятие 8.3. Представьте ситуацию: у пользователя при попытке открыть или сформировать отчет на системе компоновки данных (СКД) внезапно возникает критическая ошибка «Нарушение прав доступа!». При этом ни в подробных сведениях об ошибке, ни в стандартном Журнале регистрации никакой детальной технической информации нет. Ситуация осложняется тем, что на 32-разрядном клиенте отчет работает без каких-либо нареканий, а вот на 64-разрядной платформе стабильно выдает ошибку.

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

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

Для начала давайте разберем по шагам, что происходит в системе, когда пользователь запускает отчет на СКД:

  1. Отсутствие собственной формы: Если у отчета в конфигураторе не созданы собственные формы (поля «Основная форма отчета», «Основная форма настроек отчета» и «Основная форма варианта отчета» остаются пустыми), платформа 1С автоматически генерирует для него стандартную управляемую форму «на лету» в процессе выполнения.
  2. Автоматическое сохранение настроек: По умолчанию эта стандартная форма пытается при открытии прочитать, а при закрытии или изменении параметров — записать пользовательские настройки (выбранные варианты, отборы, условное оформление и историю использования). Для этого она обращается к системным хранилищам, таким как ХранилищеСистемныхНастроек или ХранилищеПользовательскихНастроекОтчетов.
  3. Проверка прав доступа: Если у роли текущего пользователя отключено право «Сохранение данных пользователя», то любая попытка обратиться к этим хранилищам вызывает жесткое системное исключение. Поскольку проверка прав происходит на уровне ядра СУБД/сервера еще до выполнения какого-либо кода самого отчета, событие об ошибке блокируется на низком уровне и часто не доходит до Журнала регистрации.
  4. Разница между 32-разрядной и 64-разрядной платформами: В устаревающих 32-битных клиентах платформа 1С исторически более лояльно относится к кэшированию интерфейсных настроек. Она активно использует локальные файлы пользователя на компьютере (каталоги в папке AppData) для сохранения состояния окон и настроек, при этом игнорируя или мягко обходя ошибки отсутствия прав в базе данных. В современных 64-разрядных клиентах оптимизирован механизм взаимодействия с сервером: вызовы оптимизированы, а проверка прав роли на сервере выполняется максимально строго и бескомпромиссно, что и приводит к гарантированному падению сессии с ошибкой доступа.

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

Способ 1. Использование собственного привилегированного Хранилища настроек

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

Рассмотрим по шагам реализацию этого способа:

  1. Откройте конфигуратор и в дереве метаданных найдите ветку Общие -> Хранилища настроек.
  2. Добавьте новое хранилище настроек и назовите его, например, ПривилегированноеХранилищеНастроек.
  3. В свойствах вашего проблемного отчета найдите параметры Хранилище настроек и Хранилище вариантов и укажите в них созданное нами ПривилегированноеХранилищеНастроек.
  4. Откройте модуль менеджера созданного хранилища настроек и пропишите процедуры для сохранения и загрузки данных. Чтобы сохранение работало у пользователей без прав, мы принудительно включим привилегированный режим внутри процедур.

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


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

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

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

Способ 2. Создание минимальной формы отчета с отключением автосохранения

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

Разберем по шагам, как это реализовать:

  1. В конфигураторе откройте свойства вашего отчета и перейдите на вкладку Формы.
  2. Нажмите на иконку с лупой напротив поля Форма отчета, чтобы запустить конструктор.
  3. Создайте обычную пустую управляемую форму отчета и назначьте её основной формой отчета.
  4. В дереве свойств созданной формы (в правой части экрана конфигуратора) найдите свойство Автоматическое сохранение данных в настройках (в англоязычной версии — AutoSaveDataInSettings).
  5. Установите значение этого свойства в положение Не использовать (или просто снимите соответствующий флажок).

После этого платформа перестанет автоматически вызывать транзакции сохранения данных при открытии или закрытии этой формы. Ошибка «Нарушение прав доступа!» гарантированно исчезнет, при этом вам даже не придется писать программный код.

Способ 3. Ручное управление настройками в модуле формы

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

Сначала мы отключаем свойство Автоматическое сохранение данных в настройках в свойствах формы. Затем переходим в модуль созданной управляемой формы отчета и пишем следующий код:


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

&НаКлиенте
Процедура ПриЗакрытии(ЗавершениеРаботы)
    
    Если Не ЗавершениеРаботы Тогда
        СохранитьНастройкиНаСервере();
    КонецЕсли;
    
КонецПроцедуры

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

Этот способ удобен тем, что нам не требуется создавать новые объекты метаданных (новые Хранилища настроек) в дереве конфигурации. Мы продолжаем использовать системное ХранилищеОбщихНастроек, но делаем это контролируемо и безопасно.

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

Если ваша конфигурация разработана на основе БСП (а это практически все типовые решения от фирмы 1С: ERP, Управление торговлей, Комплексная автоматизация, Бухгалтерия предприятия и др.), вы можете задействовать штатный механизм интеграции дополнительных отчетов и обработок.

Проанализируем этот вариант подробнее:

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

Резюме

Мы рассмотрели технические аспекты поведения платформы 1С:Предприятие 8.3 при формировании отчетов на СКД в 64-разрядных средах. Для исправления ошибки «Нарушение прав доступа!» без выдачи избыточных прав на интерфейс мы рекомендуем использовать Способ 1 (если отчет встроен в конфигурацию и критически важно сохранять индивидуальные настройки пользователей) или Способ 2 (если сохранение настроек отчета пользователю не требуется).

← На главную