МенеджерБезопасногоХранилища

Типы · SecureStorageManager

Используется для управления безопасным хранилищем данных на мобильном устройстве.

Полное описание, параметры и ограничения

МенеджерБезопасногоХранилища (SecureStorageManager)

МенеджерБезопасногоХранилища (SecureStorageManager)

Доступен, начиная с версии 8.3.15.

Методы:
НачатьПолучениеДанных (BeginGetData)
НачатьПомещениеДанных (BeginPutData)
НачатьУдалениеДанных (BeginDeleteData)
ПоддерживаетсяЗащитаДоступа (AccessProtectionSupported)
ПолучитьДанныеАсинх (GetDataAsync)
ПоместитьДанныеАсинх (PutDataAsync)
СодержитКлюч (ContainsKey)
УдалитьДанныеАсинх (DeleteDataAsync)

Описание:

Используется для управления безопасным хранилищем данных на мобильном устройстве.

Доступность:

Мобильный клиент, мобильное приложение (клиент).

См. также:
Глобальный контекст, свойство БезопасноеХранилище

Использование в версии:

Доступен, начиная с версии 8.3.15.

Методическая информация

Практические примеры

Собственный счет в мобильном сейфе: Ждать, полное чтение, замена и удаление

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

Где и как запускать

Собственный новый Android ARM64 developer mobile-platform app; только МобильноеПриложениеКлиент и локальный МобильноеПриложениеСервер для scalar guard. Ни desktop, ни mobile-client fallback; действительная версия показана отдельно.

Подготовка

  1. Будущий ручной опыт — только собственная новая изолированная лаборатория: отдельное Android ARM64 устройство, не личный телефон, и своя новая Windows-VM с подготовленным IIS. Здесь устройство, CF, публикация, установка и хранилище не запускались. Изучение кода само ничего не записывает.

  2. Создайте с нуля собственную конфигурацию УчебныйСейф85 без прикладных данных. Версия конфигурации ровно 58dd39ee-7b27-40aa-9bcb-552ea90cf15c; режим совместимости Не использовать; назначение использования Приложение для мобильной платформы. Метка — учебная идентификация пакета, не криптографическое доказательство и не UUID ИБ/пользователя.

  3. Общие → Общие формы: создайте ровно три управляемые формы ГлавнаяСейфа85, ПультСейфаАсинх85, ПультСейфаОповещения85. У главной формы создайте команды ОткрытьАсинх85 и ОткрытьОповещения85 с одноименными обработчиками; выведите две кнопки этих команд. Вставьте приведенный полный модуль главной формы. Поместите ГлавнаяСейфа85 в рабочую область начальной страницы конфигурации; это навигация, не автоматический запуск опыта.

  4. У каждой формы пульта создайте реквизиты СогласенНаОпыт85 (Булево, исходно Ложь), ВерсияRuntime85/Состояние85/История85 (Строка неограниченной длины), Сумма85 (Число15,2). Выведите флажок согласия и поля наблюдения; поля наблюдения ТолькоПросмотр=Да. Создайте ровно свою команду ПройтиОпыт85, обработчик ПройтиОпыт85(Команда), кнопку этой команды. В свойствах события формы ПриОткрытии назначьте ПриОткрытии(Отказ); не вызывайте обработчики сами.

  5. Полный MAIN модуль вставьте только в форму, названную в расположении соответствующей карточки. Другой пульт имеет другой полный MAIN модуль и отдельные внутренние переменные/согласие/ключ. Поддерживающий модуль ГлавнаяСейфа85 одинаков для двух карточек. Серверный helper находится внутри каждой формы, &НаСервереБезКонтекста: только МобильноеПриложениеСервер, возвращает Булево, opaque менеджер/данные/nonce через RPC не передаются.

  6. Проверка конфигурации: Мобильное приложение — клиент и Мобильное приложение — сервер, целостность, ссылки и неподдерживаемые функции. При ошибках STOP. Путь поставки: Конфигурация → Мобильное приложение → Публиковать…; только собственный новый виртуальный каталог OwnSafePackets85_<ownGUID> и собственная папка своей VM/IIS, без автоматического обновления. Публикация создает каталог/мобильную конфигурацию и может предложить обновление только своей новой ИБ; не подключайте рабочую базу. Это не сборщик APK/IPA.

  7. Для собственного Android ARM64 вручную используйте официальный пакет мобильной платформы разработчика 1cem-arm64.apk из своего фактически полученного мобильного дистрибутива. Не 1cem-client-arm64.apk и не 1cem-standalone-arm64.apk: это другие среды. Наличие Windows8.5.1.1343 не доказывает доступность/установку мобильного бинарного runtime8.5.1.1343. Здесь ничего не скачано и не установлено; неподходящий фактический пакет — STOP.

  8. После самостоятельной установки developer-платформы в пустом списке приложений нажмите +, в Address задайте реальный URL своей private VM и точное имя своей публикации, нажмите Load, задайте имя УчебныйСейф85 и завершите создание (OK/Done), затем откройте свое приложение из списка. Не localhost телефона, не file://, не выдуманный готовый URL. Android должен видеть только свою VM в лабораторной локальной сети; публичный сервер/рабочая ИБ не нужны. Не включайте auto-restart, auto-update или debugging ради этого опыта. Данные desktop-ИБ не считаются перенесенными: счет создается самим кодом на устройстве.

  9. Официальная инструкция поставки: https://1c-dn.com/library/publishing_of_1c_mobile_application/ ; вариант ARM64 и добавление приложения: https://1c-dn.com/library/tutorials/1c_enterprise_development_tools_user_guide/ ; собственная локальная мобильная ИБ и проверка конфигурации: https://1c-dn.com/library/tutorials/first_application_mobile_platform/ . Это документированный будущий путь, не подтверждение текущей установки.

  10. На своем лабораторном устройстве заранее настройте блокировку экрана; PIN/пароль не выводите и не задавайте пароль по умолчанию. Native capability ScreenUnlockRequired проверяется до каждого этапа, False означает STOP без понижения до Нет. Четвертый обязательный аргумент PutAsync — СпособДополнительнойПроверкиПользователя.БиометрическаяИлиВводПароля; в выбранном режиме он игнорируется, это не обещание биометрического успеха.

  11. Откройте только выбранный пульт. Поле ВерсияRuntime85 показывает реальную версию мобильного приложения; код требует формат8.x.x.x и минимум8.3.18 для Promise API, но это не runtime-тест конкретного устройства. Другой контекст, изменившаяся версия, ошибка API/guard/capability — STOP. Никакого запуска в desktop или замены безопасного хранилища массивом.

  12. До нажатия прочитайте весь lifecycle. Каждая форма имеет отдельное согласие, изначально False; поставьте свой флажок и один раз нажмите ПройтиОпыт85. Код сразу потребляет согласие и создает один свежий UUID ключа в своей области AWAIT или CALLBACK. Записи будущего опыта: первая форма3, вторая1; каждая удаляет ровно свой1 ключ. Данные не секретные: OWN85, UUID, коды ROW-A/ROW-B и две числовые суммы. Посторонние ключи не перечисляются, не читаются и не удаляются.

  13. При отмене, ошибке, чужом результате или неожидаемом этапе форма остается STOP/неизвестно. Нет автоматического retry/rollback/delete/cleanup. Не закрывайте и не открывайте пульт заново ради уборки: внутреннее состояние формы не обещано сохраняющимся после закрытия/перезапуска приложения. Сначала вручную выясните фактический исход только собственного ключа; инструкция не дает полномочий на чужое хранилище.

&НаКлиенте
Перем СогласиеИспользовано85, Остановка85, Неизвестно85, Этап85, Токен85,
    Ключ85, Менеджер85, Способ85, ДопПроверка85, ОжидаемыйПакет85;

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    Если СогласиеИспользовано85 <> Неопределено Или Остановка85 <> Неопределено Тогда
        Отказ = Истина;
        Возврат;
    КонецЕсли;
    СогласиеИспользовано85 = Ложь;
    Остановка85 = Истина;
    Неизвестно85 = Истина;
    СогласенНаОпыт85 = Ложь;
    Сумма85 = 0;
    История85 = "";
    Этап85 = "Подготовка";
    Попытка
        ВерсияRuntime85 = ПроверитьМобильнуюВерсию85();
        Остановка85 = Ложь;
        Неизвестно85 = Ложь;
        Этап85 = "Готов";
        Состояние85 = "Версия проверена. Прочитайте последствия и отдельно поставьте флажок согласия";
    Исключение
        Остановить85(ОписаниеОшибки());
        Отказ = Истина;
    КонецПопытки;
КонецПроцедуры

&НаКлиенте
Процедура Остановить85(Причина)
    Остановка85 = Истина;
    Неизвестно85 = Истина;
    СогласенНаОпыт85 = Ложь;
    Этап85 = "STOP";
    Состояние85 = "STOP. Исход неизвестен; повтор и автоматическая уборка запрещены. " + Причина;
КонецПроцедуры

&НаКлиенте
Процедура ПодготовитьОпыт85(Команда, Префикс)
    #Если МобильноеПриложениеКлиент Тогда
        Если ТипЗнч(Команда) <> Тип("КомандаФормы") Или Команда <> Команды.Найти("ПройтиОпыт85")
            Или СогласиеИспользовано85 <> Ложь Или Остановка85 <> Ложь Или Неизвестно85 <> Ложь
            Или Этап85 <> "Готов" Или СогласенНаОпыт85 <> Истина Тогда
            ВызватьИсключение "Нужна собственная команда и отдельное неиспользованное согласие; повтор запрещен";
        КонецЕсли;
        СогласиеИспользовано85 = Истина;
        СогласенНаОпыт85 = Ложь;
        Неизвестно85 = Истина;
        Этап85 = "Подготовка";
        Если Префикс <> "OWN_SAFE_PACKETS_85:AWAIT:" И Префикс <> "OWN_SAFE_PACKETS_85:CALLBACK:" Тогда
            ВызватьИсключение "Разрешены только две собственные учебные области ключей";
        КонецЕсли;
        Токен85 = Новый УникальныйИдентификатор;
        Ключ85 = Префикс + Строка(Токен85);
        Менеджер85 = БезопасноеХранилище;
        Способ85 = СпособЗащитыДоступаБезопасногоХранилища.ТребуетсяРазблокировкаЭкрана;
        ДопПроверка85 = СпособДополнительнойПроверкиПользователя.БиометрическаяИлиВводПароля;
        ПроверитьСостояние85("Подготовка");
        ПроверитьЗанятость85(Ложь);
        ОжидаемыйПакет85 = СоздатьПакет85(750, 250);
    #Иначе
        ВызватьИсключение "Нет мобильного клиентского контекста; хранилище не вызывается";
    #КонецЕсли
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьСостояние85(ОжидаемыйЭтап)
    #Если МобильноеПриложениеКлиент Тогда
        Если Остановка85 <> Ложь Или СогласиеИспользовано85 <> Истина
            Или СогласенНаОпыт85 <> Ложь Или Этап85 <> ОжидаемыйЭтап
            Или ТипЗнч(Неизвестно85) <> Тип("Булево")
            Или ТипЗнч(Токен85) <> Тип("УникальныйИдентификатор")
            Или ТипЗнч(Ключ85) <> Тип("Строка")
            Или (Ключ85 <> "OWN_SAFE_PACKETS_85:AWAIT:" + Строка(Токен85)
                И Ключ85 <> "OWN_SAFE_PACKETS_85:CALLBACK:" + Строка(Токен85))
            Или ТипЗнч(Менеджер85) <> Тип("МенеджерБезопасногоХранилища")
            Или Способ85 <> СпособЗащитыДоступаБезопасногоХранилища.ТребуетсяРазблокировкаЭкрана
            Или ДопПроверка85 <> СпособДополнительнойПроверкиПользователя.БиометрическаяИлиВводПароля
            Или ПроверитьМобильнуюВерсию85() <> ВерсияRuntime85 Тогда
            ВызватьИсключение "Изменились контекст, версия, собственный ключ или этап; STOP";
        КонецЕсли;
        Поддерживается = Менеджер85.ПоддерживаетсяЗащитаДоступа(Способ85, ДопПроверка85);
        Если ТипЗнч(Поддерживается) <> Тип("Булево") Или Поддерживается <> Истина Тогда
            ВызватьИсключение "ScreenUnlockRequired не поддержан; защита не понижается";
        КонецЕсли;
    #Иначе
        ВызватьИсключение "Запрещен вызов мобильного хранилища из иной среды";
    #КонецЕсли
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьЗанятость85(Ожидается)
    #Если МобильноеПриложениеКлиент Тогда
        Занят = Менеджер85.СодержитКлюч(Ключ85);
        Если ТипЗнч(Занят) <> Тип("Булево") Или Занят <> Ожидается Тогда
            ВызватьИсключение "Фактическая занятость собственного ключа не совпала";
        КонецЕсли;
    #Иначе
        ВызватьИсключение "Проверка ключа допустима только в мобильном приложении";
    #КонецЕсли
КонецПроцедуры

&НаКлиенте
Функция СоздатьПакет85(ПерваяСумма, ВтораяСумма)
    Если ТипЗнч(ПерваяСумма) <> Тип("Число") Или ТипЗнч(ВтораяСумма) <> Тип("Число")
        Или (ПерваяСумма <> 750 И ПерваяСумма <> 250) Или ВтораяСумма <> 250 Тогда
        ВызватьИсключение "В этом конечном учебном пакете допустимы только 750/250 или 250/250";
    КонецЕсли;
    Возврат "OWN85|" + Строка(Токен85) + "|ROW-A|" + Формат(ПерваяСумма, "ЧГ=0;ЧДЦ=0")
        + "|ROW-B|" + Формат(ВтораяСумма, "ЧГ=0;ЧДЦ=0");
КонецФункции

&НаКлиенте
Функция ПроверитьПолныйПакет85(Данные, ПерваяСумма, ВтораяСумма)
    Если Данные = Неопределено Тогда
        ВызватьИсключение "Нет подтвержденных данных: возможна отмена; STOP";
    КонецЕсли;
    Если ТипЗнч(Данные) <> Тип("Строка") Тогда
        ВызватьИсключение "Ожидалась настоящая строка собственного пакета";
    КонецЕсли;
    Если Данные <> ОжидаемыйПакет85 Или Данные <> СоздатьПакет85(ПерваяСумма, ВтораяСумма) Тогда
        ВызватьИсключение "Не совпала вся фактически прочитанная строка";
    КонецЕсли;
    Части = СтрРазделить(Данные, "|", Истина);
    Если Части.Количество() <> 6 Или Части[0] <> "OWN85"
        Или Части[1] <> Строка(Токен85) Или Части[2] <> "ROW-A" Или Части[4] <> "ROW-B" Тогда
        ВызватьИсключение "Не совпали число частей, nonce или оба кода строк";
    КонецЕсли;
    Первая = Число(Части[3]);
    Вторая = Число(Части[5]);
    Если ТипЗнч(Первая) <> Тип("Число") Или ТипЗнч(Вторая) <> Тип("Число")
        Или Первая <> ПерваяСумма Или Вторая <> ВтораяСумма Тогда
        ВызватьИсключение "Не совпали обе фактически разобранные числовые суммы";
    КонецЕсли;
    Возврат Первая + Вторая;
КонецФункции

&НаКлиенте
Процедура ПроверитьОтсутствиеОтмены85(Результат)
    Если ТипЗнч(Результат) <> Тип("Булево") Или Результат <> Ложь Тогда
        ВызватьИсключение "Отмена или неизвестный результат native операции; STOP";
    КонецЕсли;
КонецПроцедуры
&НаКлиенте
Функция ПроверитьМобильнуюВерсию85()
    #Если МобильноеПриложениеКлиент Тогда
        Информация = Новый СистемнаяИнформация;
        Версия = Информация.ВерсияПриложения;
        Если ПроверитьСвойПакетНаСервере85() <> Истина Тогда
            ВызватьИсключение "Локальный сервер не подтвердил метку собственного пакета";
        КонецЕсли;
        Возврат Версия;
    #Иначе
        ВызватьИсключение "Этот урок запускается только в мобильном приложении, не в desktop или мобильном клиенте";
    #КонецЕсли
КонецФункции
&НаКлиенте
Асинх Функция ПрочитатьОжидаемый85(ПерваяСумма, ВтораяСумма, НужныйЭтап)
    #Если МобильноеПриложениеКлиент Тогда
        ПроверитьСостояние85(НужныйЭтап);
        ПроверитьЗанятость85(Истина);
        Неизвестно85 = Истина;
        Операция = Менеджер85.ПолучитьДанныеАсинх(Ключ85, "Прочитать только собственный учебный счет");
        Если Операция = Неопределено Тогда
            ВызватьИсключение "GetAsync сразу вернул Неопределено; продолжение запрещено";
        КонецЕсли;
        Если ТипЗнч(Операция) <> Тип("Обещание") Тогда
            ВызватьИсключение "GetAsync не вернул обещание";
        КонецЕсли;
        Данные = Ждать Операция;
        ПроверитьСостояние85(НужныйЭтап);
        Если Неизвестно85 <> Истина Тогда
            ВызватьИсключение "Ожидалось незавершенное собственное чтение";
        КонецЕсли;
        Сумма = ПроверитьПолныйПакет85(Данные, ПерваяСумма, ВтораяСумма);
        ПроверитьЗанятость85(Истина);
        Неизвестно85 = Ложь;
        Возврат Сумма;
    #Иначе
        ВызватьИсключение "GetAsync не вызывается в иной среде";
    #КонецЕсли
КонецФункции

&НаКлиенте
Асинх Процедура ПройтиОпыт85(Команда)
    Попытка
        #Если МобильноеПриложениеКлиент Тогда
            ПодготовитьОпыт85(Команда, "OWN_SAFE_PACKETS_85:AWAIT:");
            Этап85 = "НачальнаяЗапись";
            ПроверитьСостояние85("НачальнаяЗапись");
            Неизвестно85 = Истина;
            Операция = Менеджер85.ПоместитьДанныеАсинх(Ключ85, ОжидаемыйПакет85, Способ85, ДопПроверка85);
            Если ТипЗнч(Операция) <> Тип("Обещание") Тогда
                ВызватьИсключение "PutAsync не вернул обещание";
            КонецЕсли;
            Результат = Ждать Операция;
            ПроверитьСостояние85("НачальнаяЗапись");
            ПроверитьОтсутствиеОтмены85(Результат);
            Сумма85 = Ждать ПрочитатьОжидаемый85(750, 250, "НачальнаяЗапись");
            Если Сумма85 <> 1000 Тогда ВызватьИсключение "Исходный счет не равен 1000"; КонецЕсли;
            История85 = "1000";
            Этап85 = "Замена";
            Сумма85 = Ждать ПрочитатьОжидаемый85(750, 250, "Замена");
            ПроверитьСостояние85("Замена");
            НовыйПакет = СоздатьПакет85(250, 250);
            Неизвестно85 = Истина;
            Операция = Менеджер85.ПоместитьДанныеАсинх(Ключ85, НовыйПакет, Способ85, ДопПроверка85);
            Если ТипЗнч(Операция) <> Тип("Обещание") Тогда
                ВызватьИсключение "Replacement PutAsync не вернул обещание";
            КонецЕсли;
            Результат = Ждать Операция;
            ПроверитьСостояние85("Замена");
            ПроверитьОтсутствиеОтмены85(Результат);
            ОжидаемыйПакет85 = НовыйПакет;
            Сумма85 = Ждать ПрочитатьОжидаемый85(250, 250, "Замена");
            Если Сумма85 <> 500 Тогда ВызватьИсключение "Измененный счет не равен 500"; КонецЕсли;
            История85 = История85 + " → 500";
            Этап85 = "Восстановление";
            Сумма85 = Ждать ПрочитатьОжидаемый85(250, 250, "Восстановление");
            ПроверитьСостояние85("Восстановление");
            ИсходныйПакет = СоздатьПакет85(750, 250);
            Неизвестно85 = Истина;
            Операция = Менеджер85.ПоместитьДанныеАсинх(Ключ85, ИсходныйПакет, Способ85, ДопПроверка85);
            Если ТипЗнч(Операция) <> Тип("Обещание") Тогда
                ВызватьИсключение "Restoration PutAsync не вернул обещание";
            КонецЕсли;
            Результат = Ждать Операция;
            ПроверитьСостояние85("Восстановление");
            ПроверитьОтсутствиеОтмены85(Результат);
            ОжидаемыйПакет85 = ИсходныйПакет;
            Сумма85 = Ждать ПрочитатьОжидаемый85(750, 250, "Восстановление");
            Если Сумма85 <> 1000 Тогда ВызватьИсключение "Восстановленный счет не равен 1000"; КонецЕсли;
            История85 = История85 + " → 1000";
            Этап85 = "Удаление";
            Сумма85 = Ждать ПрочитатьОжидаемый85(750, 250, "Удаление");
            ПроверитьСостояние85("Удаление");
            Неизвестно85 = Истина;
            Операция = Менеджер85.УдалитьДанныеАсинх(Ключ85);
            Если ТипЗнч(Операция) <> Тип("Обещание") Тогда
                ВызватьИсключение "DeleteAsync не вернул обещание";
            КонецЕсли;
            Результат = Ждать Операция;
            ПроверитьСостояние85("Удаление");
            ПроверитьОтсутствиеОтмены85(Результат);
            ПроверитьЗанятость85(Ложь);
            Неизвестно85 = Ложь;
            Этап85 = "Завершен";
            Состояние85 = "Подтверждено: 1000 → 500 → 1000; собственный точный ключ теперь отсутствует";
        #Иначе
            ВызватьИсключение "Мобильный опыт не запускается в другой среде";
        #КонецЕсли
    Исключение
        Остановить85(ОписаниеОшибки());
    КонецПопытки;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПроверитьСвойПакетНаСервере85()
    #Если МобильноеПриложениеСервер Тогда
        Если Метаданные.ОбщиеФормы.Количество() <> 3 Или Метаданные.ОбщиеФормы.Найти("ГлавнаяСейфа85") = Неопределено Или Метаданные.ОбщиеФормы.Найти("ПультСейфаАсинх85") = Неопределено Или Метаданные.ОбщиеФормы.Найти("ПультСейфаОповещения85") = Неопределено Тогда
            ВызватьИсключение "Не совпадает собственный новый мобильный учебный пакет";
        КонецЕсли;
        Возврат Истина;
    #Иначе
        ВызватьИсключение "Нужен локальный сервер собственного мобильного приложения, не desktop ИБ";
    #КонецЕсли
КонецФункции
Полный модуль собственной начальной формы: две настоящие команды без автоматического опыта

Своя CF → Общие → Общие формы → ГлавнаяСейфа85 → полный управляемый модуль

МобильноеПриложениеКлиент; серверный helper только МобильноеПриложениеСервер. Сначала своя метка и фактическая версия, затем ОткрытьФорму своей общей формы; записи/чтения сейфа не выполняются.

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

&НаКлиенте
Процедура ОткрытьОповещения85(Команда)
    Если ТипЗнч(Команда) <> Тип("КомандаФормы") Или Команда <> Команды.Найти("ОткрытьОповещения85") Тогда
        ВызватьИсключение "Нужна собственная команда главной формы оповещений";
    КонецЕсли;
    ПроверитьМобильнуюВерсию85();
    ОткрытьФорму("ОбщаяФорма.ПультСейфаОповещения85");
КонецПроцедуры
&НаКлиенте
Функция ПроверитьМобильнуюВерсию85()
    #Если МобильноеПриложениеКлиент Тогда
        Информация = Новый СистемнаяИнформация;
        Версия = Информация.ВерсияПриложения;
        Если ПроверитьСвойПакетНаСервере85() <> Истина Тогда
            ВызватьИсключение "Локальный сервер не подтвердил метку собственного пакета";
        КонецЕсли;
        Возврат Версия;
    #Иначе
        ВызватьИсключение "Этот урок запускается только в мобильном приложении, не в desktop или мобильном клиенте";
    #КонецЕсли
КонецФункции
&НаСервереБезКонтекста
Функция ПроверитьСвойПакетНаСервере85()
    #Если МобильноеПриложениеСервер Тогда
        Если Метаданные.ОбщиеФормы.Количество() <> 3 Или Метаданные.ОбщиеФормы.Найти("ГлавнаяСейфа85") = Неопределено Или Метаданные.ОбщиеФормы.Найти("ПультСейфаАсинх85") = Неопределено Или Метаданные.ОбщиеФормы.Найти("ПультСейфаОповещения85") = Неопределено Тогда
            ВызватьИсключение "Не совпадает собственный новый мобильный учебный пакет";
        КонецЕсли;
        Возврат Истина;
    #Иначе
        ВызватьИсключение "Нужен локальный сервер собственного мобильного приложения, не desktop ИБ";
    #КонецЕсли
КонецФункции

Разбор по шагам

  1. Откройте собственный пульт, прочитайте фактическую версию и последствия3 записей/1 удаления; отдельно согласитесь.

  2. Из нового nonce создаются точный ключ и пакет750+250; capability должен быть True, ContainsKey своего ключаFalse.

  3. Настоящий PutAsync имеет4 аргумента; BoolFalse после Ждать означает отсутствие отмены. GetAsync должен вернуть Promise, затем всю собственную строку и сумму1000.

  4. Повторно прочитайте исходный целый пакет перед replacement. Запишите250+250 и настоящим новым чтением подтвердите500.

  5. Повторно прочитайте измененный пакет перед restoration. Запишите750+250 и новым чтением подтвердите1000.

  6. Еще раз прочитайте весь восстановленный пакет перед DeleteAsync; только после BoolFalse и фактического ContainsKeyFalse опыт завершен.

Как проверить результат

  1. MAIN получает настоящий МенеджерБезопасногоХранилища через readonly global; объект не создается выдуманным конструктором.

  2. После каждого Ждать/callback проверяются текущий этап, типы, версия, метка собственной CF и native capability; неизвестный исход не разрешает новую операцию.

  3. Каждое фактическое чтение сравнивает всю строку,6 частей, свой UUID, оба кода и обе преобразованные числовые суммы.

  4. Before replacement/restoration/deletion источник прочитан заново; чужой либо изменившийся пакет вызывает STOP.

  5. Каждый опыт имеет собственный consumed-consent и свой новый nonce-ключ. Никаких чужих ключей, ручных событий и автоматического восстановления.

Ожидаемый результат

Ожидаемый ручной результат: История85 = 1000 → 500 → 1000, Сумма85=1000; только созданный этим пультом ключ отсутствует. Runtime здесь не проверен.

На что обратить внимание

  1. BoolFalse у Put/DeleteAsync — признак отсутствия отмены, не доказательство сохранения/удаления: нужны реальные контрольные чтения.

  2. GetAsync документирует Promise или прямое Неопределено; неопределенные конечные данные тоже STOP, поскольку свой producer никогда не сохраняет Неопределено.

  3. ContainsKey означает только занятость конкретного ключа и не выполняет пользовательскую проверку. Он не доказывает пустоту всего сейфа.

  4. BeginPut исключен: установленная справка противоречит сама себе в типе четвертого аргумента. Не угадываем другой enum или отсутствующий обязательный параметр.

  5. Sticky STOP и consumed-consent относятся к текущему экземпляру формы; нет обещания сохранения состояния после закрытия/переустановки.

  6. Чтение с последующей записью не является атомарным CAS или доказательством отсутствия гонки; используйте только свой отдельный стенд и единственного оператора.

  7. Будущий ручной код действительно использует защищенное хранилище, ОС I/O и возможные системные проверки. Здесь не было runtime и криптографического теста.

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

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.