Тип: HTTPЗапрос. Содержит запрос на аутентфикацию второго фактора.
Полное описание, параметры и ограничения
ШаблонНастройкиВторогоФактораАутентификации.HTTPЗапросНаАутентификацию (SecondAuthenticationFactorSettingTemplate.AuthenticationHTTPRequest)
ШаблонНастройкиВторогоФактораАутентификации (SecondAuthenticationFactorSettingTemplate)
HTTPЗапросНаАутентификацию (AuthenticationHTTPRequest)
Доступен, начиная с версии 8.3.14.
Использование:
Чтение и запись.
Описание:
Тип: HTTPЗапрос.
Содержит запрос на аутентфикацию второго фактора.
Доступность:
Сервер, толстый клиент.
Примечание:
Свойство должно быть заполнено.
Использование в версии:
Доступен, начиная с версии 8.3.14.
Методическая информация
Практические примеры
Создать и разобрать два своих native шаблона второго фактора без записи
Полная штатная фабрика → два HTTP child → два собственных шаблона → локальный consumer двух строк. Каждый реальный native field сверяется с конечным собственным источником, а хранилище остаётся пустым. Это не вход, не вызов провайдера и не рекомендация безопасности.
Где и как запускать
Полный общий модуль МФА85Черновики: только неглобальный Server+ServerCall; собственная новая FileCF Windows/толстый управляемый клиент.
Подготовка
Этот опыт — каталог объектов настройки, а не работающий второй фактор входа. Никакие HTTP-запросы, MFA, SMS, почта, реальные секреты, QR или токены здесь не выполняются. Все действия ниже выполняет человек только в будущей новой своей лаборатории; авторство/статические проверки не создавали ИБ и не меняли настройки.
В отдельной новой Windows VM вручную создайте совершенно новую файловую ИБ, не копию рабочей: C:\1c-labs\OwnMFATemplates85_2fac7b4e-b263-4cc1-86e5-09d540f0f380\IB. В Конфигураторе: имя конфигурации УчебныеШаблоныМФА85, платформа 8.5.1.1343, режим совместимости НеИспользовать, ОсновнойРежимЗапуска УправляемоеПриложение. Никаких объектов данных, регистров, обработок, сервисов, заданий, подписок, разделителей или расширений.
Создайте только одну роль ШаблоныМФА85. В её свойствах прав конфигурации явно предоставьте Администрирование, АдминистрированиеДанных, АктивныеПользователи, запуск собственного толстого клиента и открытие собственной общей формы. Native ПолучитьПользователей требует административных прав; ПолучитьСоединенияИнформационнойБазы требует АктивныеПользователи. Совпадение имени роли не доказывает её права, реальные отказы не обходятся.
Через Администрирование → Пользователи в своей новой ИБ создайте ровно одного нового пользователя МФА85Ученик, назначьте только свою роль. Не используйте действующий рабочий пароль и не показывайте его в учебнике. НастройкиВторогоФактораАутентификации должны быть пустым native массивом; здесь эти настройки только читаются/Количество=0 и не создаются. Закройте Конфигуратор перед опытом, оставьте одно соединение своего пользователя.
Создайте два неглобальных общих модуля МФА85Черновики и МФА85Хранилище: Сервер Да, ВызовСервера Да; КлиентОбычноеПриложение Нет, КлиентУправляемоеПриложение Нет, ВнешнееСоединение Нет, Привилегированный Нет; ПовторноеИспользованиеВозвращаемыхЗначений НеИспользовать. Первый MAIN вставьте целиком в первый модуль, второй MAIN целиком во второй. В обоих полные свои helpers; никакого импорта неизвестной обработки или БСП.
Создайте одну общую управляемую форму ШаблоныМФА85. Реквизиты: ПаспортUUID85 Строка(36), Текст85 Строка неограниченной длины, Согласие85 Булево, Шаг85 Строка(7). Поля привяжите через ПутьКДанным к одноимённым реквизитам; ПаспортUUID85 и Текст85 только просмотр. Команды Просмотр85 и ОдинЭтап85 с одноимёнными действиями/кнопками. События ПриСозданииНаСервере2/ПриОткрытии1 назначьте настоящим обработчикам полного FORM. APP целиком разместите в модуле управляемого приложения, ПриНачалеРаботыСистемы0. Нативные события вручную не вызывайте.
Обновите только эту новую конфигурацию базы, закройте Конфигуратор, запустите собственный толстый управляемый клиент. Серверный Паспорт85 проверяет точный File-путь, версию/NoUse, пустую модель, состав модулей/формы/роли, одного фактического пользователя с его UUID, пустые настройки второго фактора и одно соединение. UUID реквизита — реальный UUID пользователя из штатной фабрики, не UUID пути/шаблона. В следующих RPC он сверяется до и после действий.
Нажмите Просмотр85 до каких-либо записей. Получите две строки A/B и 0 сохранённых шаблонов. СоздатьШаблон() — реальная native фабрика; Новый Шаблон... и Новый Менеджер... отсутствуют и не применяются. GetTemplates0/FindByName1 читают полное состояние; исходное хранилище обязано быть пустым. При чужом шаблоне/пользователе/несовпадении СТОП, ничего не удалять.
Наш конечный fixture: имена MFA85_A_2fac7b4e-b263-4cc1-86e5-09d540f0f380 и MFA85_B_2fac7b4e-b263-4cc1-86e5-09d540f0f380. У каждого native HTTPЗапрос для start и result, POST/POST, ровно Content-Type=application/json и X-Own-Lab=<UUID>. Четыре ASCII URI относительные, без host: /own-mfa85/<UUID>/A/start, /A/result, /B/start, /B/result. Body — ровно собственный JSON lab/slot/action, UTF8 и НеИспользоватьBOM; это несекретные данные local preview, не поддерживаемый реальный провайдер.
Для опыта записи выберите saveA, отдельно явно установите Согласие85 и нажмите ОдинЭтап85. Полный whitelist 0 проверяется перед Записать0, затем свежие GetTemplates/FindByName и все пять native полей с полными полями двух HTTP child проверяются в состоянии A/1. Согласие потребляется перед RPC. Потом выберите saveB и дайте новое согласие: состояние AB/2. Это будущая попытка записи только своих новых шаблонов, не применение MFA к пользователю.
Удаление — два отдельных намеренных этапа, не автоматическое исправление: deleteB с новым согласием проверяет полный AB/2 и удаляет только найденный собственный B, затем свежий A/1. deleteA с новым согласием проверяет A/1, затем пустое /0. Нельзя выбирать этап лишь по количеству: код проверяет все имена, типы, методы, URI, заголовки, тела и наличие/отсутствие обоих точных имён.
Записать() и Удалить() — процедуры, без возвращаемого Булево. Ни False, ни вымышленная ссылка не подставляются как признак успеха. После любой ошибки RPC, native операции, readback или обработки результата пульт sticky СТОП и снимает согласие. Исход записи/удаления может быть неизвестен; повтор, rollback и автоматическое удаление не делаются. Не переоткрывайте форму ради снятия СТОП: сначала отдельно исследуйте фактическое состояние собственной лаборатории.
ПолучитьТелоКакСтроку возвращает Строка/Неопределено; fresh persisted readback может отказать. Тогда СТОП без выдуманного тела, чтения неизвестного файла или продолжения удаления. Readback не гарантирует атомарность/отсутствие конкурентных изменений. Мы не обещаем, что хранение запроса доказывает его отправку, подстановку secret, совместимость с провайдером или успешный MFA вход.
В HBK GetTemplates/FindByName написано право Администратор, Create/Write/Delete — Администрирование. Это формулировки справки, не предлагаемый новый enum права или имя роли. Одноаргументной ПравоДоступа нет; реальные штатные ошибки сохраняются. НастройкаВторогоФактораАутентификации, её неподтверждённая фабрика и enum обработчика НЕ входят в PRIMARY этих двух уроков.
Функция Паспорт85() Экспорт
Если СтрокаСоединенияИнформационнойБазы() <> "File=""C:\1c-labs\OwnMFATemplates85_2fac7b4e-b263-4cc1-86e5-09d540f0f380\IB"";" Тогда
ВызватьИсключение "Только новая собственная файловая ИБ по точному пути";
КонецЕсли;
Если Метаданные.РежимСовместимости <> Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать Или ПривилегированныйРежим() Или ТранзакцияАктивна() Тогда
ВызватьИсключение "Не совпали версия/своя конфигурация/NoUse/непривилегированный контекст";
КонецЕсли;
Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0
Или Метаданные.Константы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0
Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0
Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0
Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0
Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0
Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0
Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0
Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Или Метаданные.HTTPСервисы.Количество() <> 0
Или Метаданные.WebСервисы.Количество() <> 0 Или Метаданные.СервисыИнтеграции.Количество() <> 0
Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0
Или Метаданные.Отчеты.Количество() <> 0 Или Метаданные.Обработки.Количество() <> 0 Тогда
ВызватьИсключение "Только пустая собственная прикладная модель без интеграций и заданий";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации()
Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.БазаДанных).Количество() <> 0
Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансАктивные).Количество() <> 0
Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансОтключенные).Количество() <> 0 Тогда
ВызватьИсключение "Расширения базы и сеанса запрещены";
КонецЕсли;
Если Метаданные.ОбщиеМодули.Количество() <> 2 Или Метаданные.ОбщиеФормы.Количество() <> 1
Или Метаданные.ОбщиеФормы.Найти("ШаблоныМФА85") = Неопределено Или Метаданные.Роли.Количество() <> 1 Тогда
ВызватьИсключение "Нужны только два своих модуля, один пульт и одна роль";
КонецЕсли;
Для Каждого ИмяМодуля Из СтрРазделить("МФА85Черновики,МФА85Хранилище", ",") Цикл
Модуль = Метаданные.ОбщиеМодули.Найти(ИмяМодуля);
Если Модуль = Неопределено Тогда
ВызватьИсключение "Нет полного собственного серверного модуля";
КонецЕсли;
Если Модуль.Глобальный Или Не Модуль.Сервер Или Не Модуль.ВызовСервера
Или Модуль.КлиентОбычноеПриложение Или Модуль.КлиентУправляемоеПриложение
Или Модуль.ВнешнееСоединение Или Модуль.Привилегированный
Или Модуль.ПовторноеИспользованиеВозвращаемыхЗначений <> Метаданные.СвойстваОбъектов.ПовторноеИспользованиеВозвращаемыхЗначений.НеИспользовать Тогда
ВызватьИсключение "Оба модуля только Server+ServerCall, без привилегий и кеша";
КонецЕсли;
КонецЦикла;
Пользователь = ПользователиИнформационнойБазы.ТекущийПользователь();
Если Пользователь = Неопределено Или ТипЗнч(Пользователь) <> Тип("ПользовательИнформационнойБазы") Тогда
ВызватьИсключение "Нет настоящего текущего пользователя";
КонецЕсли;
Если Пользователь.Имя <> "МФА85Ученик" Тогда
ВызватьИсключение "Только собственный учебный пользователь";
КонецЕсли;
Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
Если ТипЗнч(Пользователи) <> Тип("Массив") Или Пользователи.Количество() <> 1 Тогда
ВызватьИсключение "Должен быть только один собственный пользователь";
КонецЕсли;
Свой = Пользователи[0];
Если ТипЗнч(Свой) <> Тип("ПользовательИнформационнойБазы") Или Свой.Имя <> Пользователь.Имя
Или Свой.УникальныйИдентификатор <> Пользователь.УникальныйИдентификатор Тогда
ВызватьИсключение "Полный свежий список не совпал с пользователем собственного сеанса";
КонецЕсли;
Настройки = Свой.НастройкиВторогоФактораАутентификации;
Если ТипЗнч(Настройки) <> Тип("Массив") Или Настройки.Количество() <> 0 Тогда
ВызватьИсключение "Нельзя сохранять или удалять учебные шаблоны, связанные с настройками пользователя";
КонецЕсли;
СвояРоль = Метаданные.Роли.Найти("ШаблоныМФА85");
Если СвояРоль = Неопределено Или Не Свой.Роли.Содержит(СвояРоль) Тогда
ВызватьИсключение "Нет собственной явно подготовленной роли";
КонецЕсли;
ЧислоРолей = 0;
Для Каждого Роль Из Свой.Роли Цикл
Если Роль <> СвояРоль Тогда
ВызватьИсключение "Чужая роль запрещена";
КонецЕсли;
ЧислоРолей = ЧислоРолей + 1;
КонецЦикла;
Если ЧислоРолей <> 1 Или ПолучитьСоединенияИнформационнойБазы().Количество() <> 1 Тогда
ВызватьИсключение "Только своя единственная роль и одно соединение";
КонецЕсли;
Возврат Строка(Свой.УникальныйИдентификатор);
КонецФункции
Функция ИмяШаблона85(Слот)
Если Слот <> "A" И Слот <> "B" Тогда
ВызватьИсключение "Разрешены только собственные два слота A/B";
КонецЕсли;
Возврат "MFA85_" + Слот + "_2fac7b4e-b263-4cc1-86e5-09d540f0f380";
КонецФункции
Функция Адрес85(Слот, Действие)
ИмяШаблона85(Слот);
Если Действие <> "start" И Действие <> "result" Тогда
ВызватьИсключение "Только собственные start/result";
КонецЕсли;
Возврат "/own-mfa85/2fac7b4e-b263-4cc1-86e5-09d540f0f380/" + Слот + "/" + Действие;
КонецФункции
Функция Тело85(Слот, Действие)
Адрес85(Слот, Действие);
Возврат "{""lab"":""2fac7b4e-b263-4cc1-86e5-09d540f0f380"",""slot"":""" + Слот + """,""action"":""" + Действие + """}";
КонецФункции
Функция СобственныйЗапрос85(Слот, Действие)
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "application/json");
Заголовки.Вставить("X-Own-Lab", "2fac7b4e-b263-4cc1-86e5-09d540f0f380");
Запрос = Новый HTTPЗапрос(Адрес85(Слот, Действие), Заголовки);
Запрос.УстановитьТелоИзСтроки(Тело85(Слот, Действие), КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
ПроверитьЗапрос85(Запрос, Слот, Действие);
Возврат Запрос;
КонецФункции
Процедура ПроверитьЗапрос85(Запрос, Слот, Действие)
Если ТипЗнч(Запрос) <> Тип("HTTPЗапрос") Тогда
ВызватьИсключение "Нужен настоящий собственный HTTPЗапрос, не структурная подмена";
КонецЕсли;
Если ТипЗнч(Запрос.АдресРесурса) <> Тип("Строка") Или Запрос.АдресРесурса <> Адрес85(Слот, Действие)
Или ТипЗнч(Запрос.Заголовки) <> Тип("Соответствие") Или Запрос.Заголовки.Количество() <> 2 Тогда
ВызватьИсключение "Не совпали полный собственный URI без host и число заголовков";
КонецЕсли;
Для Каждого Заголовок Из Запрос.Заголовки Цикл
Если ТипЗнч(Заголовок.Ключ) <> Тип("Строка") Или ТипЗнч(Заголовок.Значение) <> Тип("Строка") Тогда
ВызватьИсключение "Заголовки собственного запроса должны быть строковыми";
КонецЕсли;
Если Заголовок.Ключ = "Content-Type" Тогда
Если Заголовок.Значение <> "application/json" Тогда
ВызватьИсключение "Не совпал собственный Content-Type";
КонецЕсли;
ИначеЕсли Заголовок.Ключ = "X-Own-Lab" Тогда
Если Заголовок.Значение <> "2fac7b4e-b263-4cc1-86e5-09d540f0f380" Тогда
ВызватьИсключение "Чужой UUID заголовка";
КонецЕсли;
Иначе
ВызватьИсключение "Чужой заголовок запрещён";
КонецЕсли;
КонецЦикла;
Тело = Запрос.ПолучитьТелоКакСтроку();
Если Тело = Неопределено Или ТипЗнч(Тело) <> Тип("Строка") Или Тело <> Тело85(Слот, Действие) Тогда
ВызватьИсключение "Тело изменено или не возвращается как строка; СТОП без чтения неизвестного файла";
КонецЕсли;
КонецПроцедуры
Функция СоздатьСвойШаблон85(Слот)
Шаблон = ШаблоныНастроекВторогоФактораАутентификации.СоздатьШаблон();
Если ТипЗнч(Шаблон) <> Тип("ШаблонНастройкиВторогоФактораАутентификации") Тогда
ВызватьИсключение "Нужен объект настоящей штатной фабрики";
КонецЕсли;
Шаблон.Имя = ИмяШаблона85(Слот);
Шаблон.HTTPЗапросНаАутентификацию = СобственныйЗапрос85(Слот, "start");
Шаблон.МетодHTTPЗапросаНаАутентификацию = "POST";
Шаблон.HTTPЗапросНаПроверкуРезультатаАутентификации = СобственныйЗапрос85(Слот, "result");
Шаблон.МетодHTTPЗапросаНаПроверкуРезультатаАутентификации = "POST";
ПроверитьШаблон85(Шаблон, Слот);
Возврат Шаблон;
КонецФункции
Процедура ПроверитьШаблон85(Шаблон, Слот)
Если ТипЗнч(Шаблон) <> Тип("ШаблонНастройкиВторогоФактораАутентификации") Тогда
ВызватьИсключение "Нужен настоящий native шаблон";
КонецЕсли;
Если ТипЗнч(Шаблон.Имя) <> Тип("Строка") Или Шаблон.Имя <> ИмяШаблона85(Слот)
Или ТипЗнч(Шаблон.МетодHTTPЗапросаНаАутентификацию) <> Тип("Строка") Или Шаблон.МетодHTTPЗапросаНаАутентификацию <> "POST"
Или ТипЗнч(Шаблон.МетодHTTPЗапросаНаПроверкуРезультатаАутентификации) <> Тип("Строка") Или Шаблон.МетодHTTPЗапросаНаПроверкуРезультатаАутентификации <> "POST" Тогда
ВызватьИсключение "Имя или методы собственных запросов изменены";
КонецЕсли;
ПроверитьЗапрос85(Шаблон.HTTPЗапросНаАутентификацию, Слот, "start");
Если Шаблон.HTTPЗапросНаПроверкуРезультатаАутентификации = Неопределено Тогда
ВызватьИсключение "У нашего собственного finite fixture обязателен запрос результата";
КонецЕсли;
ПроверитьЗапрос85(Шаблон.HTTPЗапросНаПроверкуРезультатаАутентификации, Слот, "result");
КонецПроцедуры
Процедура СверитьХранилище85(Ожидаемые)
Фактические = ШаблоныНастроекВторогоФактораАутентификации.ПолучитьШаблоны();
Если ТипЗнч(Фактические) <> Тип("Массив") Или Фактические.Количество() <> СтрДлина(Ожидаемые) Тогда
ВызватьИсключение "Полный объём шаблонов не совпал с собственным состоянием";
КонецЕсли;
Встреченные = Новый Соответствие;
Для Каждого Шаблон Из Фактические Цикл
Если ТипЗнч(Шаблон) <> Тип("ШаблонНастройкиВторогоФактораАутентификации") Тогда
ВызватьИсключение "Чужой тип элемента хранилища";
КонецЕсли;
Слот = "";
Для Позиция = 1 По СтрДлина(Ожидаемые) Цикл
Кандидат = Сред(Ожидаемые, Позиция, 1);
Если Шаблон.Имя = ИмяШаблона85(Кандидат) Тогда
Слот = Кандидат;
КонецЕсли;
КонецЦикла;
Если Слот = "" Или Встреченные.Получить(Слот) <> Неопределено Тогда
ВызватьИсключение "Чужой или повторный шаблон запрещён";
КонецЕсли;
ПроверитьШаблон85(Шаблон, Слот);
Встреченные.Вставить(Слот, Истина);
КонецЦикла;
Для Каждого Слот Из СтрРазделить("A,B", ",") Цикл
Найденный = ШаблоныНастроекВторогоФактораАутентификации.НайтиПоИмени(ИмяШаблона85(Слот));
Если СтрНайти(Ожидаемые, Слот) > 0 Тогда
ПроверитьШаблон85(Найденный, Слот);
ИначеЕсли Найденный <> Неопределено Тогда
ВызватьИсключение "Отсутствующий по whitelist шаблон найден в свежем поиске";
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция ПоказатьЧерновики85(ОжидаемыйUUID) Экспорт
Если ТипЗнч(ОжидаемыйUUID) <> Тип("Строка") Или Паспорт85() <> ОжидаемыйUUID Тогда
ВызватьИсключение "Собственный фактический UUID пользователя изменился";
КонецЕсли;
СверитьХранилище85("");
Менеджер = ШаблоныНастроекВторогоФактораАутентификации;
Если ТипЗнч(Менеджер) <> Тип("МенеджерШаблоновНастроекВторогоФактораАутентификации") Тогда
ВызватьИсключение "Нужен настоящий native manager, не Новый и не структура";
КонецЕсли;
Черновики = Новый Массив;
Черновики.Добавить(СоздатьСвойШаблон85("A"));
Черновики.Добавить(СоздатьСвойШаблон85("B"));
Вывод = "Собственный local preview; не аутентификация и не вызов провайдера:";
ЧислоСтрок = 0;
Для Каждого Шаблон Из Черновики Цикл
ЧислоСтрок = ЧислоСтрок + 1;
Слот = Сред("AB", ЧислоСтрок, 1);
ПроверитьШаблон85(Шаблон, Слот);
Вывод = Вывод + Символы.ПС + Шаблон.Имя
+ "; " + Шаблон.МетодHTTPЗапросаНаАутентификацию + " " + Шаблон.HTTPЗапросНаАутентификацию.АдресРесурса
+ "; " + Шаблон.МетодHTTPЗапросаНаПроверкуРезультатаАутентификации + " " + Шаблон.HTTPЗапросНаПроверкуРезультатаАутентификации.АдресРесурса;
КонецЦикла;
Если ЧислоСтрок <> 2 Тогда
ВызватьИсключение "Consumer должен прочитать два actual native черновика";
КонецЕсли;
Если Паспорт85() <> ОжидаемыйUUID Тогда
ВызватьИсключение "Контекст пользователя изменился после просмотра";
КонецЕсли;
СверитьХранилище85("");
Возврат Вывод + Символы.ПС + "Строк=2; сохранённых шаблонов=0. Все имена/методы/URI/заголовки/тела проверены, запросы не отправлялись.";
КонецФункцииПолный модуль собственной общей управляемой формы
ОбщаяФорма.ШаблоныМФА85.Модуль
Толстый управляемый клиент: команды1, ПриОткрытии1; сервер формы: ПриСозданииНаСервере2. RPC только строки/Булево.
&НаКлиенте
Перем Остановлен85;
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ПаспортUUID85 = МФА85Черновики.Паспорт85();
Текст85 = "Сначала только собственный preview. Согласие на запись/удаление выключено.";
Согласие85 = Ложь;
Шаг85 = "saveA";
КонецПроцедуры
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если Остановлен85 <> Неопределено Тогда
ВызватьИсключение "Повторная инициализация не снимает СТОП";
КонецЕсли;
Остановлен85 = Ложь;
КонецПроцедуры
&НаКлиенте
Процедура Просмотр85(Команда)
Если Остановлен85 <> Ложь Тогда
ВызватьИсключение "СТОП: не повторяйте неизвестный опыт";
КонецЕсли;
Остановлен85 = Истина;
Попытка
Итог = МФА85Черновики.ПоказатьЧерновики85(ПаспортUUID85);
Если ТипЗнч(Итог) <> Тип("Строка") Тогда
ВызватьИсключение "RPC должен вернуть только собственный текст, не native объекты";
КонецЕсли;
Текст85 = Итог;
Остановлен85 = Ложь;
Исключение
Остановлен85 = Истина;
Согласие85 = Ложь;
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
&НаКлиенте
Процедура ОдинЭтап85(Команда)
Если Остановлен85 <> Ложь Тогда
ВызватьИсключение "СТОП: состояние базы нужно отдельно исследовать, не сбрасывать флаг";
КонецЕсли;
Если Согласие85 <> Истина Тогда
ВызватьИсключение "Сначала прочитайте выбранный этап и явно установите согласие";
КонецЕсли;
Разрешение = Согласие85;
Согласие85 = Ложь;
Остановлен85 = Истина;
Попытка
Итог = МФА85Хранилище.ВыполнитьШаг85(Шаг85, Разрешение, ПаспортUUID85);
Если ТипЗнч(Итог) <> Тип("Строка") Тогда
ВызватьИсключение "RPC возврат или последующая проверка не завершены";
КонецЕсли;
Текст85 = Итог;
Остановлен85 = Ложь;
Исключение
Остановлен85 = Истина;
Согласие85 = Ложь;
ВызватьИсключение;
КонецПопытки;
КонецПроцедурыПолный модуль собственного управляемого приложения
Модуль управляемого приложения своей новой CF
Толстый управляемый клиент, настоящее ПриНачалеРаботыСистемы0.
Процедура ПриНачалеРаботыСистемы()
ОткрытьФорму("ОбщаяФорма.ШаблоныМФА85");
КонецПроцедурыРазбор по шагам
Проверить точный собственный File-паспорт и реальный UUID одного lab-пользователя, настройки второго фактора 0.
Свежим GetTemplates/FindByName подтвердить пустое хранилище и отсутствие обоих точных имён.
Создать A/B реальной фабрикой, заполнить пять native свойств и четыре полных HTTP запроса без host.
Consumer читает actual имена/методы/URI/headers/bodies и выводит две строки, не заменяет объекты expected литералами.
Повторно подтвердить собственный паспорт и 0 сохранённых шаблонов; ни Записать, ни Удалить в MAIN не вызываются.
Как проверить результат
Два native шаблона и две строки local preview; хранилище перед/после 0.
Все пять свойств, четыре URI/body и полные finite headers фактически проверены.
Настройки пользователя не создаются и не записываются, запросы никуда не отправляются.
Ожидаемый результат
Реальные draft-объекты изучены в цельной ограниченной задаче; native/type/static сверка не является запуском MFA.
На что обратить внимание
Шаблон HTTP-запроса не является отправкой.
Порядок returned GetTemplates не используется для распознавания A/B: полный поиск по именам.
Если получен Неопределено вместо body string или фабрики ожидаемого типа, СТОП.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.