Функции Azure и файл кэша постоянных токенов

#c# #azure-functions #msal

Вопрос:

У меня есть функция, запускаемая HTTP (.NET 3.1 TLS, работающая не из zip-пакета), которая подключается к моему личному OneDrive и удаляет файлы. Чтобы свести к минимуму запросы на проверку подлинности, я использовал этот подход для сериализации кэша токенов: https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-net-token-cache-serialization?tabs=custom#simple-token-cache-serialization-msal-only

На локальном хосте это отлично работает, но при запуске функции в Azure это не так хорошо — файл кэша довольно часто теряется. Я включил Path.GetTemporaryPath() . Не уверен, какое место лучше всего подходит для этой цели. Однако кэш, похоже, привязан к компьютеру, создавшему файл: когда я использую файл кэша, созданный на моем локальном хосте и загруженный в Azure, использование такого файла показывает ошибки при получении сведений об учетной записи / перечислении.

Есть идеи, как это исправить с минимальными затратами? Мое приложение использует только один токен: для моего личного OneDrive.

Комментарии:

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

2. Используйте надежные функции и сохраняйте токен в надежном объекте

3. Спасибо, это может быть хорошим вариантом. Я также только что понял, что код из ссылки шифрует файл с помощью docs.microsoft.com/en-us/dotnet/api/… . Поэтому я постараюсь не шифровать его , потому что это ограничивает расшифровку одним профилем/машиной. Тогда я могу попытаться сохранить » байт[]» как прочную сущность.

4. Я протестировал его , и длительное состояние не сильно помогло 🙁 После более или менее одного часа бездействия состояние класса было очищено, и мне нужно было снова пройти аутентификацию ;-( Я попробую большой двоичный объект хранилища Azure..

5. Вы работаете в среде без сервера. Каждый вызов вашей функции потенциально выполняется на другой виртуальной машине, в результате чего любое локально сохраненное состояние теряется. Для постоянного хранилища вам следует переключиться на хранилище azure или какое-либо другое хранилище длительного хранения, например базу данных или хранилище функций длительного хранения.

Ответ №1:

Окончательное решение заключается в:

  • удалите ProtectedData из кода из примера помощника по сериализации пользовательских токенов, поскольку он шифрует файл с текущим профилем или машиной
  • сохраните args.TokenCache.DeserializeMsalV большой двоичный объект хранилища Azure и прочитайте его позже.

Поэтому я внес изменения в код с https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-net-token-cache-serialization?tabs=custom#simple-token-cache-serialization-msal-only к следующему:

Включает сериализацию:

 string cstring = System.Environment.GetEnvironmentVariable("AzureWebJobsStorage");
string containerName = System.Environment.GetEnvironmentVariable("TokenCacheStorageContainer");
        try { bcc = new BlobContainerClient(cstring, containerName); } catch { }
        if (!bcc.Exists())
        {
            bcc = (new BlobServiceClient(cstring)).CreateBlobContainerAsync(containerName).GetAwaiter().GetResult();
        }
        tokenCache.SetBeforeAccess(BeforeAccessNotification);
        tokenCache.SetAfterAccess(AfterAccessNotification);
 

Перед зачислением:

 lock (FileLock)
        {
            var blob = bcc.GetBlobClient("msalcache.bin3");
            if (blob.Exists())
            {
                var stream = new MemoryStream();
                blob.DownloadToAsync(stream).GetAwaiter().GetResult();
                args.TokenCache.DeserializeMsalV3(stream.ToArray());
            }
        }
 

После зачисления:

 if (args.HasStateChanged)
        {
            lock (FileLock)
            {
                // reflect changesgs in the persistent store
                (bcc.GetBlobClient("msalcache.bin3")).UploadAsync(new MemoryStream(args.TokenCache.SerializeMsalV3()),true).GetAwaiter().GetResult();
            }
        }