Вопрос по iphone, ios – iOS KeyChain не получает значения из фона

77

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

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 версии связки ключей, но все равно получаю те же результаты. Буду признателен за любые отзывы по этому поводу. Это лишь небольшая часть моих пользователей, но это проблема, которую я хотел бы исправить и не беспокоиться. Заранее спасибо.

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

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

Ваш Ответ

3   ответа
100

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

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

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

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

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

повторяя @JoeyHagedorn здесь - слушайте сессию WWDC 2013 года 204 "Что нового с многозадачностью" на отметке 44:24 и WWDC 2013, сессия 709 «Защита секретов с помощью брелка»; в 25:30. Вы можете увидеть текстовое содержание этих выступлений наasciiwwdc.com
Мы буквально занимались этим неделями. Вы спасатель жизни!
Спасибо! Это было очень полезно.
Пожалуйста, избегайте…AccessibleAlways если это вообще возможно, или сохраните токен, который предоставляет только ограниченные привилегии (например, токен, который позволяет читать новые элементы фида, но не публиковать их). При этом вы явно отказываетесь от уровня шифрования. Если ваше приложение может подождать до первой разблокировки, возможно, будет лучше использовать…AfterFirstUnlock и попросите пользователей сначала разблокировать их устройства.
Это действительно плохая идея, потому что это означает, что эти учетные данные больше не защищены. Хотя немного больше работы, важно создатьderivative credential чем можно использовать только для ограниченного доступа, который, как вы ожидаете, потребуется в фоновом режиме и не более. Срок действия этих ограниченных учетных данных может истечь через некоторое время, и каждый раз при открытии приложения создается новый, аннулирующий старые. Это обеспечивает безопасность пользователя в случае компрометации производных учетных данных. Обратитесь к сессии 204 WWDC 2013, чтобы услышать об этом.
1

В моем случае watchOS2 получает доступ к данным цепочки для ключей на стороне iOS.

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

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

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

52

использованиеkSecAttrAccessibleAfterFirstUnlock вместоkSecAttrAccessibleAlways.


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

kSecAttrAccessibleAfterFirstUnlock
The data in the keychain item cannot be accessed after a restart until the device has been unlocked once by the user.

After the first unlock, the data remains accessible until the next restart. This is recommended for items that need to be accessed by background applications. Items with this attribute migrate to a new device when using encrypted backups.

Этот ответ должен быть комментарием & # x2026;

Похожие вопросы