Подтвердить что ты не робот

IOS KeyChain не извлекает значения из фона

В настоящее время я храню имя пользователя (адрес электронной почты) и соленый хэш электронной почты и пароля в iOS KeyChain. Я использую версию ARC'ified, найденную здесь.

KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MyCustomIdentifier" accessGroup:nil];
[wrapper setObject:APP_NAME forKey:(__bridge id)kSecAttrService];
[wrapper setObject:email forKey:(__bridge id)kSecAttrAccount];
[wrapper setObject:token forKey:(__bridge id)kSecValueData];

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

Имейте в виду, что это происходит только эпизодически, и мне еще нужно привязать его к конкретной версии или устройству iOS.

Пользователь отправляет местоположение (мониторинг региона), и я хочу обновить сервер своим статусом. Я пытаюсь вытащить токен из брелка, так же, как и для каждого другого сетевого вызова, и обновить статус. Но для некоторых пользователей значение равно нулю. Без этого я не могу обновить сетевые материалы. Почему это работает для большинства, но не для небольшого процента?

KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MyCustomIdentifier" accessGroup:nil];
NSString *token = [wrapper objectForKey:(__bridge id)kSecValueData];

Я вернулся к не-ARC-версии keychainwrapper, но все же получаю те же результаты. Я был бы признателен за любые отзывы об этом. Это лишь небольшая часть моих пользователей, но это проблема, которую я хотел бы исправить и не беспокоиться. Спасибо заранее.

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

ИЗМЕНИТЬ Я выяснил свою проблему, когда они связывают цепочку, не извлекая значения из фона. Я отправлю ответ ниже и приму его, поскольку я чувствую, что этот вопрос может стать ценным для других позже.

4b9b3361

Ответ 1

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

Заблокированные домашние экраны. Учебники по keychain всегда оставляли настройки доступности для брелока для ключей, поэтому он по умолчанию будет использовать самый низкий/безопасный уровень доступа Apple. Однако этот уровень не позволяет получить доступ к ключам, если у пользователя есть код доступа на экране блокировки. Бинго! Это объясняет спорадическое поведение и почему это происходит только с небольшим процентом пользователей.

Одна строка кода, решает весь беспорядок.

[wrapper setObject:(__bridge id)kSecAttrAccessibleAlways forKey:(__bridge id)kSecAttrAccessible];

Добавьте эту строку, где я устанавливаю значения имени пользователя и пароля. Работает как шарм. Надеюсь, это поможет кому-то там. Это немного смутило меня, пока я не смог собрать кусочки.

Ответ 2

Используйте kSecAttrAccessibleAfterFirstUnlock вместо kSecAttrAccessibleAlways.


От Документация Apple:

kSecAttrAccessibleAfterFirstUnlock
Данные в объекте keychain не могут получить доступ после перезапуска, пока устройство не будет разблокировано один раз пользователем.

После первой разблокировки данные остаются доступными до следующего перезапуск. Рекомендуется для элементов, к которым необходимо получить доступ фоновых приложений. Элементы с этим атрибутом переносятся на новый устройства при использовании зашифрованных резервных копий.

Ответ 3

В моем случае watchOS2 обращается к данным связки ключей на стороне iOS.

В начале используется kSecAttrAccessibleWhenUnlockedThisDeviceOnly. Я могу читать данные независимо от того, что iPhone заблокирован или нет. Мне очень стыдно, что я получу Ошибка, когда часы попытаются получить доступ к цепочке ключей: : SecTrustEvaluate [лист ЭмитентКоммерное имя SubjectCommonName]

И в каком-то случае это станет: : SecOSStatusWith error: [- 25308] Ошибка домена = NSOSStatusErrorDomain Code = -25308 "ks_crypt: e00002e2 не удалось выполнить команду" oe "(класс 6, сумка: 0) Доступ к объекту, предпринятому при блокировке брелка." UserInfo = {NSDescription = ks_crypt: e00002e2 не удалось выполнить команду "oe" (класс 6, сумка: 0) Доступ к объекту, пытающемуся, когда брелок заблокирован.}

Я обновлю свой ответ, если я получу дополнительную информацию.