Почему не работают новые параметры сеанса в расширениях для 1С:Фреш и как решить эту проблему?

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

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

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

Выясняем причину: почему платформа разрешает, а 1С:Фреш блокирует?

Начиная с версии платформы 8.3.14, разработчикам официально разрешено добавлять собственные параметры сеанса в расширениях. Их можно использовать для хранения различных глобальных переменных, контекста пользователя и даже в механизмах ограничения доступа на уровне записей (RLS). Однако в облаке 1С:Фреш эта технология сталкивается с непреодолимыми архитектурными барьерами:

  1. Невозможность расширения системных модулей инициализации. Для того чтобы параметр сеанса можно было использовать, его необходимо инициализировать при старте системы. Стандартное событие УстановкаПараметровСеанса располагается в объекте МодульСеанса. Платформа «1С:Предприятие» накладывает жесткий запрет на перехват или изменение Модуля сеанса и Модуля управляемого приложения через расширения. Попытка инициализировать параметры через обработчики типа ПередНачаломРаботыПриложения в расширении часто происходит слишком поздно, когда платформа уже обратилась к параметрам сеанса (например, при инициализации интерфейса или RLS) и выдала ошибку их отсутствия.
  2. Ограничения безопасного режима (Safe Mode). Все пользовательские расширения в 1С:Фреш в обязательном порядке работают в строгом безопасном режиме. При инициализации параметров сеанса практически всегда требуется выполнять запросы к базе данных или обращаться к служебным механизмам, что требует использования привилегированного режима. Безопасный режим расширения полностью блокирует программное включение привилегированного режима для незаимствованных объектов. Платформа расценивает такое действие как нарушение безопасности и выбрасывает исключение, которое внешне выглядит так, будто у пользователя просто нет прав на этот параметр сеанса.
  3. Разделение данных в мультиарендной архитектуре (SaaS). Сервис 1С:Фреш работает по технологии разделения данных. Параметры разделения (такие как ОбластьДанныхЗначение) инициализируются на самых ранних этапах старта сеанса, задолго до того, как контекст вашего расширения будет полностью загружен в память и готов к работе. Попытка обратиться к параметрам сеанса расширения в этот момент приводит к конфликту ядра платформы.

Таким образом, использование параметров сеанса в расширениях для 1С:Фреш технически нежизнеспособно. Единственный правильный путь — переписать архитектуру хранения сеансовых данных. Рассмотрим подробнее, как это сделать.

Решение 1: Использование регистра сведений с измерением «Пользователь» (Рекомендуемый способ)

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

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

  1. В расширении создаем новый регистр сведений (например, с именем ПараметрыСеансаРасширения).
  2. Устанавливаем режим записи — Запись независимая.
  3. Добавляем измерение Пользователь с типом ссылки на справочник пользователей (например, СправочникСсылка.Пользователи).
  4. Добавляем ресурсы для каждого параметра, который мы планировали хранить в сеансе (например, ТекущийСклад, ОсновнаяОрганизация).

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


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

Для чтения параметра в любом месте конфигурации мы можем использовать простую функцию получения значения:


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

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

Решение 2: Общие модули с повторным использованием значений (Кэширование)

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

Рассмотрим, как это реализовать:

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

Посмотрим на пример кода такого модуля:


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

Каждый раз, когда в коде расширения вам потребуется обратиться к этим настройкам, вы просто вызываете:

Настройки = КэшСеансаРасширенияПовтИсп.ПолучитьНастройкиТекущегоПользователя();

Платформа автоматически вернет закэшированную структуру при втором и последующих вызовах. Это работает быстрее, чем параметры сеанса, и абсолютно легитимно с точки зрения требований 1С:Фреш.

Решение 3: Функциональные опции

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

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

Сравнительный анализ решений

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

  1. Регистр сведений:
    • Плюсы: Простота реализации, надежное хранение данных между сеансами (данные не сбрасываются при перезапуске программы), полная поддержка в безопасном режиме.
    • Минусы: При каждом получении данных происходит обращение к базе данных (хотя оно очень быстрое благодаря индексам по измерениям).
  2. Общие модули с повторным использованием:
    • Плюсы: Максимальная скорость работы (данные берутся прямо из оперативной памяти сервера приложений), не нагружает СУБД.
    • Минусы: Кэш сбрасывается при завершении сеанса пользователя или при перезапуске рабочего процесса сервера «1С:Предприятия». Подходит только для чтения данных (нельзя динамически "перезаписать" кэш в процессе сеанса без сброса кэша всего модуля).
  3. Функциональные опции:
    • Плюсы: Идеально для автоматического управления видимостью и доступностью элементов интерфейса и реквизитов на уровне платформы.
    • Минусы: Требует понимания механизмов работы функциональных опций и их правильной привязки к метаданным в расширении.

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

← На главную