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

· 9 мин

Содержание

Параметры сеанса в 1С инициализируют в модуле сеанса, в процедуре-обработчике УстановкаПараметровСеанса(ТребуемыеПараметры). Платформа вызывает её при старте сеанса с ТребуемыеПараметры = Неопределено, а потом — каждый раз, когда код обращается к параметру, у которого ещё нет значения. Тогда в ТребуемыеПараметры приходит массив имён, и обработчик обязан установить каждый из них.

Механизм общий для платформы 8.3 и не зависит от конфигурации. Различается только обвязка: в своей конфигурации вы пишете обработчик целиком, а в типовых на БСП регистрируете свою процедуру в общем механизме. Ниже — оба варианта, типы значений, права и приёмы отладки.

Как устроены параметры сеанса и для чего их заводят

Параметр сеанса — это значение, которое живёт ровно столько, сколько живёт сеанс пользователя. Оно хранится на сервере, у каждого сеанса своё, и другие сеансы его не видят.

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

  • 👤 ссылку на текущего пользователя из справочника Пользователи;
  • 🏢 основную организацию или склад пользователя;
  • 🔐 значения для ограничения доступа на уровне записей (RLS);
  • ⚙️ признаки режима работы: обмен, загрузка данных, работа в сервисе.

Главная особенность — параметры сеанса доступны в текстах ограничений доступа ролей. В условии RLS к параметру обращаются через амперсанд, например &ТекущийПользователь. Поэтому без правильно проинициализированного параметра ломается не только прикладной код, но и права.

Чем отличаетсяПараметр сеансаГлобальная переменная модуля приложенияОбщий модуль с повторным использованием
Где хранитсяНа сервере, в сеансеНа клиентеКеш на клиенте или сервере
Доступен в RLSДаНетНет
Можно изменить из кодаДа, при наличии праваДаТолько сбросом кеша
Виден фоновому заданиюНет, у задания свой сеансНетНет

Объявление параметра сеанса в конфигураторе

Прежде чем что-то инициализировать, параметр нужно описать в метаданных.

  1. Откройте конфигуратор и дерево конфигурации.
  2. Разверните ветку Общие → Параметры сеанса.
  3. Нажмите Добавить и задайте Имя, например ТекущийСклад.
  4. Укажите Тип. Для склада — СправочникСсылка.Склады.
  5. Откройте нужные роли и выставьте для параметра права Получение и, если пользователь должен менять значение сам, Установка.
  6. Обновите конфигурацию базы данных.

У параметра сеанса нет свойства «значение по умолчанию». Пока обработчик не присвоил значение, параметр считается неустановленным. Это не то же самое, что пустая ссылка или Неопределено.

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

Какой тип выбрать

Параметр сеанса не может хранить изменяемые коллекции. Массив, структуру или соответствие перед записью превращают в фиксированный аналог:

МассивОрганизаций = ПолучитьДоступныеОрганизации();
ПараметрыСеанса.ДоступныеОрганизации = Новый ФиксированныйМассив(МассивОрганизаций);

Тип параметра в метаданных при этом задают как ФиксированныйМассив. Если нужно сохранить что-то более сложное, используют ХранилищеЗначения, но такой параметр нельзя использовать в условиях RLS.

Инициализация значений в модуле сеанса

Модуль сеанса открывают из контекстного меню корня конфигурации: команда Открыть модуль сеанса. В нём объявляют процедуру-обработчик с фиксированным именем.

Два режима вызова

Значение ТребуемыеПараметрыКогда приходитЧто делать
НеопределеноОдин раз при старте сеансаУстановить то, что нужно всегда, или ничего
Массив строк с именамиПри первом обращении к неустановленному параметруУстановить каждый параметр из массива

Первый режим соблазняет заполнить всё сразу. Делать так не стоит: каждый запрос в старте сеанса замедляет вход пользователя, а половина параметров в этом сеансе может так и не понадобиться. Надёжнее «ленивая» схема: при старте ничего не делаем, параметр вычисляется в момент первого обращения.

Рабочий шаблон обработчика

Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)

	Если ТребуемыеПараметры = Неопределено Тогда
		// Старт сеанса: параметры заполняются по требованию
		Возврат;
	КонецЕсли;

	Для Каждого ИмяПараметра Из ТребуемыеПараметры Цикл

		Если ИмяПараметра = "ТекущийПользователь" Тогда
			ПараметрыСеанса.ТекущийПользователь = НайтиТекущегоПользователя();

		ИначеЕсли ИмяПараметра = "ТекущийСклад" Тогда
			ПараметрыСеанса.ТекущийСклад = ОпределитьСкладПользователя();

		ИначеЕсли ИмяПараметра = "ДоступныеОрганизации" Тогда
			ПараметрыСеанса.ДоступныеОрганизации =
				Новый ФиксированныйМассив(ПолучитьДоступныеОрганизации());

		КонецЕсли;

	КонецЦикла;

КонецПроцедуры

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

Функция НайтиТекущегоПользователя()

	ПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ ПЕРВЫЕ 1
	|	Пользователи.Ссылка КАК Ссылка
	|ИЗ
	|	Справочник.Пользователи КАК Пользователи
	|ГДЕ
	|	Пользователи.ИдентификаторПользователяИБ = &Идентификатор";
	Запрос.УстановитьПараметр("Идентификатор", ПользовательИБ.УникальныйИдентификатор);

	Выборка = Запрос.Выполнить().Выбрать();
	Если Выборка.Следующий() Тогда
		Возврат Выборка.Ссылка;
	КонецЕсли;

	Возврат Справочники.Пользователи.ПустаяСсылка();

КонецФункции

Неопределено против пустой ссылки

Путаница здесь типичная. Неопределено в аргументе обработчика — это сигнал «идёт старт сеанса», а не значение параметра.

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

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

Как установить и изменить значение параметра сеанса из кода

Записать значение можно не только в модуле сеанса. Это обычное присваивание на сервере:

ПараметрыСеанса.ТекущийСклад = НовыйСклад;

Ограничения такие:

  1. 🖥️ Свойство ПараметрыСеанса есть на сервере, во внешнем соединении и в толстом клиенте. В тонком и веб-клиенте его нет — читать и писать придётся через серверную процедуру, вызываемую с клиента.
  2. 🔑 Для записи нужно право Установка. Модуль сеанса выполняется в привилегированном режиме, поэтому там проверок нет. В остальном коде, если у роли права нет, оборачивайте присваивание в привилегированный режим.
  3. 🧩 Значение должно соответствовать объявленному типу.

Шаблон смены склада по команде пользователя:

&НаСервереБезКонтекста
Процедура УстановитьТекущийСкладНаСервере(Склад)

	УстановитьПривилегированныйРежим(Истина);
	ПараметрыСеанса.ТекущийСклад = Склад;
	УстановитьПривилегированныйРежим(Ложь);

КонецПроцедуры

Не открывайте право «Установка» на параметры, участвующие в RLS. Если пользователь может сам записать ТекущийПользователь, он подменит себе ограничения доступа. Такие параметры меняют только в привилегированном режиме из проверенного кода.

Как сбросить значение, если исходные данные изменились

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

Есть два способа это исправить:

  • 🔄 при записи справочника, где хранится настройка, сразу перезаписать параметр в текущем сеансе (если правку делает сам пользователь);
  • 🚪 для чужих сеансов — попросить пользователя перезапустить программу: менять параметры другого сеанса из кода нельзя.

Область видимости и жизненный цикл значения

Значение параметра принадлежит сеансу. Отсюда несколько следствий, которые регулярно ловят на практике.

Фоновые задания. Каждое фоновое задание — отдельный сеанс. Параметры сеанса оно не наследует от запустившего его пользователя: в задании снова вызывается УстановкаПараметровСеанса, а пользователь там может быть другим. Нужные значения передавайте в задание явно, массивом параметров метода ФоновыеЗадания.Выполнить.

Регламентные задания. Выполняются от имени пользователя, указанного в свойствах задания. Если пользователь не задан, обработчик должен корректно отработать без него — например, записать пустую ссылку.

Внешнее соединение и HTTP-сервисы. Каждое подключение начинает свой сеанс, и обработчик срабатывает так же, как при интерактивном входе. Тяжёлый код при старте сеанса здесь особенно заметен.

Запросы. В тексте ограничения доступа параметр сеанса подставляется сам. В обычном запросе надёжнее передать его явно:

Запрос.УстановитьПараметр("Склад", ПараметрыСеанса.ТекущийСклад);
Диагностика: выберите симптом

Инициализация параметров сеанса в типовых конфигурациях и расширениях

В БП 3.0, ЗУП 3.1, УТ 11 и других конфигурациях на Библиотеке стандартных подсистем модуль сеанса уже занят. Он передаёт управление в БСП, а та вызывает зарегистрированные обработчики. Править модуль сеанса типовой не нужно.

Свой параметр регистрируют в процедуре ПриДобавленииОбработчиковУстановкиПараметровСеанса общего модуля ОбщегоНазначенияПереопределяемый:

Процедура ПриДобавленииОбработчиковУстановкиПараметровСеанса(Обработчики) Экспорт

	Обработчики.Вставить("ТекущийСклад", "МойМодульСервер.УстановкаПараметровСеанса");

КонецПроцедуры

Сам обработчик в экспортном серверном модуле получает имя параметра и структуру уже установленных:

Процедура УстановкаПараметровСеанса(ИмяПараметра, УстановленныеПараметры) Экспорт

	Если ИмяПараметра = "ТекущийСклад" Тогда
		ПараметрыСеанса.ТекущийСклад = ОпределитьСкладПользователя();
		УстановленныеПараметры.Добавить(ИмяПараметра);
	КонецЕсли;

КонецПроцедуры

Тип второго аргумента и порядок регистрации сверяйте с документацией вашей версии БСП: сигнатура менялась между редакциями библиотеки. Посмотреть живой пример проще всего в самой конфигурации — найдите глобальным поиском по модулям строку ПриДобавленииОбработчиковУстановкиПараметровСеанса и откройте любой типовой обработчик.

Если доработка идёт через расширение

Параметр сеанса можно добавить прямо в расширение и там же проинициализировать. Для этого в модуле сеанса расширения перехватывают УстановкаПараметровСеанса с аннотацией &После:

&После("УстановкаПараметровСеанса")
Процедура Расш1_УстановкаПараметровСеанса(ТребуемыеПараметры)

	Если ТребуемыеПараметры = Неопределено Тогда
		Возврат;
	КонецЕсли;

	Если ТребуемыеПараметры.Найти("Расш1_ТекущийСклад") <> Неопределено Тогда
		ПараметрыСеанса.Расш1_ТекущийСклад = Расш1_ОпределитьСклад();
	КонецЕсли;

КонецПроцедуры

Префикс расширения в имени параметра защищает от конфликта с объектами типовой при обновлении.

Отладка инициализации и частые промахи разработчиков

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

Как поймать обработчик в отладчике

  1. Поставьте точку останова в УстановкаПараметровСеанса.
  2. Запустите клиент из конфигуратора командой Отладка → Начать отладку. Так отладчик подключён с первой секунды сеанса.
  3. Для серверной базы убедитесь, что отладка на сервере разрешена, иначе серверные точки останова не сработают.
  4. Если процедура вызывается лениво, точка сработает в момент первого обращения к параметру, а не при входе.

Вычисление выражения ПараметрыСеанса.ТекущийСклад в табло отладчика само по себе запускает обработчик, если параметр ещё не установлен. Отладчик меняет поведение программы — помните об этом, когда разбираете «плавающую» ошибку.

Промахи, которые встречаются чаще прочих

  • 🔁 Взаимная зависимость. Параметр А вычисляется через параметр Б, а Б — через А. Обработчик вызывает сам себя, пока не упадёт стек. Разорвите цепочку: пусть один из них считается без обращения к другому.
  • 🐢 Запросы в цикле при старте. Пять параметров по запросу на каждый — пять обращений к базе на входе. Ленивая схема убирает их из старта.
  • 🧱 Изменяемая коллекция. Попытка записать Массив в параметр типа ФиксированныйМассив заканчивается ошибкой. Оборачивайте в Новый ФиксированныйМассив(...).
  • 🙈 Параметр для RLS без значения. Если обработчик не заполнил параметр, который используется в ограничении доступа, пользователь получает ошибку при открытии любого списка с этим ограничением.
  • 🗂️ Кеш вместо параметра. Для настроек, которые меняются чаще, чем раз за сеанс, параметр сеанса не подходит. Лучше читать значение по месту или использовать модуль с повторным использованием на время вызова.

Частые вопросы

Можно ли задать параметру сеанса значение по умолчанию в конфигураторе?
Нет. Такого свойства нет: значение появляется только после присваивания в коде, обычно в обработчике УстановкаПараметровСеанса.
Сохраняется ли значение параметра сеанса после выхода из программы?
Нет. Значение живёт до конца сеанса. При следующем входе оно вычисляется заново. Для постоянного хранения используйте регистр сведений или хранилище настроек.
Как прочитать параметр сеанса из модуля управляемой формы?
Только в серверной процедуре формы или через серверный общий модуль. В клиентском контексте свойства ПараметрыСеанса нет.
Сколько параметров сеанса можно создать?
Жёсткого практического лимита для прикладной разработки нет. Ограничение другое: каждый параметр, установленный при старте, удлиняет вход, поэтому их держат ленивыми.
Видит ли администратор значения параметров сеанса других пользователей?
Штатных средств для просмотра чужих значений нет. Консоль кластера показывает сами сеансы, но не значения их параметров.