SecureStorage не создает исключения, если ключ не существует

#xamarin #xamarin.forms #xamarin.ios #xamarin.essentials

Вопрос:

У меня в приложении произошла любопытная ошибка.

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

 public static async Task TrySetAsync(string key, string value)
    {
        try
        {
            await SecureStorage.SetAsync(key, value);
        }
        catch (Exception ex)
        {
            await App.Current.MainPage.DisplayAlert(
                "Device incompatible",
                "Your device is not compatible with this app.",
                "Ok");
        }
    }
 

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

 protected override async void OnAppearing()
    {
        try
        {
            // Try to save data to a random container
            string tempKey = System.Guid.NewGuid().ToString();

            //  Should throw an exception if SecureStorage is not compatible
            await Xamarin.Essentials.SecureStorage
                .SetAsync(tempKey, string.Empty);

            // Remove the datum
            Xamarin.Essentials.SecureStorage
                .Remove(tempKey);
        }
        catch
        {
            await App.Current.MainPage.DisplayAlert(
                "Device incompatible", 
                "This device does not support secure storage required for the application.", 
                "Ok");

            App.Terminate();
        }


        base.OnAppearing();
    }
 

Я удалил Права из проекта, чтобы проверить свою маленькую стряпню, и все же она проходит через него без проблем. Никаких исключений не возникает. Но при входе в систему, где используется исходный метод TrySetAsync (первый фрагмент кода), возникает ожидаемое исключение (отсутствует право). Отладчик входит в блок try и оставляет его без проблем.

Вкратце:

Похоже, что приложение не требует никаких прав, когда на SecureStorage ссылаются в OnAppearing (), но вызывает ожидаемое исключение в TrySetAsync (…), определенное в основном классе приложения.

Есть какие-нибудь советы?

P.S. Первоначально я использовал GetAsync со случайной строкой guid в OnAppearing(), которую я изменил на SetAsync и удалил, подумав, что, возможно, получение данных не требует совместимости. В общем, у меня никогда не было такой проблемы с SecureStorage, и мне это действительно кажется какой-то внутренней ошибкой.

ответ

Я виноват в использовании строки.Пусто как значение. Похоже, что SecureStorage.SetAsync проигнорирует такое значение и не сохранит его, что в результате вообще не вызовет никаких исключений. Кроме того, попытка синхронизации несуществующего ключа из SecureStorage также не приведет к исключению отсутствия права

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

1. Крайне маловероятно (я склонен сказать, что это невозможно), что расположение кода позволяет использовать несуществующее право. Гораздо более вероятно, что симптом, который вы наблюдали, не означает, что право сработало. Я понятия не имею, как могло случиться, что исключение не было выдано, но я бы проверил более тщательно. Тщательный тест заключается в том, чтобы сохранить значение в securestorage, а затем прочитать его обратно в другую переменную. Используйте линии записи отладки, чтобы узнать, выполняются ли все эти строки кода, и выяснить, правильно ли значение, возвращенное из хранилища.

2. Прогноз: Если у вас есть строка записи отладки после первого вызова securestorage, эта строка никогда не будет выполнена. Также не будет никаких следующих строк в этом блоке try. Если это предсказание окажется верным, то мы исследуем, что это значит. Также добавьте строку записи отладки в качестве первой строки catch . Меня не удивит, если DisplayAlert что-то не получится, когда все будет сделано внутри OnAppearing .

3. Кроме того, вы проверили панель вывода VS, чтобы узнать, были ли какие-либо предупреждения или сообщения об ошибках во время выполнения этого кода?

4. Привет, Стив, извини за длинный ответ, я смог сесть за него только сегодня. Следуя вашему совету, я написал более подробный тест и обнаружил, что есть два случая, когда исключение не возникает: 1. значение в SetAsync-строка. Пустой или нулевой: приложение игнорирует значение и не сохраняет его, исключение не создается. 2. ключ, на который ссылается GetAsync, в настоящее время не существует в связке ключей устройства: fetch возвращает значение null (как и ожидалось) и не создает исключения. За исключением этих двух случаев, код работает так, как ожидалось. Мне просто не повезло (и я был немного глуп) использовать строку. Пусто и не вызывает как Get, так и Set

5. Я отредактирую свой исходный вопрос, чтобы он содержал ответ, и сообщу об этом как о проблеме на их GitHub. Спасибо за помощь

Ответ №1:

(ОП сами ответили на этот вопрос):

Я виноват в использовании строки.Пусто как значение. Похоже, что SecureStorage.SetAsync проигнорирует такое значение и не сохранит его, что в результате вообще не вызовет никаких исключений. Кроме того, попытка синхронизации несуществующего ключа из SecureStorage также не приведет к исключению отсутствия права