iOS KeyChain ruft keine Werte aus dem Hintergrund ab

85

Ich speichere derzeit den Benutzernamen (E-Mail) und einen gesalzenen Hash der E-Mail und des Passworts in iOS KeyChain. Ich verwende die ARC'ified Version gefunden hier .

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];

Dies alles funktioniert einwandfrei, wenn ich das Token für meine Netzwerkanrufe herausziehen muss, während die App aktiv ist. Es funktioniert für die Anmeldung von einem sauberen Start sowie für alle Netzwerkanrufe im gesamten Gebäude. Das Problem beginnt, wenn sich die App im Hintergrund befindet.

Denken Sie daran, dass dies nur sporadisch geschieht und ich es noch nicht auf eine bestimmte iOS-Version oder ein bestimmtes iOS-Gerät festgelegt habe.

Der Benutzer löst einen Standort aus (Regionsüberwachung) und ich möchte den Server mit seinem Status aktualisieren. Ich versuche, das Token wie bei jedem anderen Netzwerkanruf aus dem Schlüsselbund zu ziehen und den Status zu aktualisieren. Für einige Benutzer ist der Wert jedoch Null. Ohne sie kann ich das Netzwerkmaterial nicht aktualisieren. Warum sollte dies für die meisten funktionieren, aber nicht für einen kleinen Prozentsatz?

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

Ich bin zur Nicht-ARC-Version des Schlüsselbundverpackers zurückgekehrt, erhalte aber immer noch die gleichen Ergebnisse. Ich würde mich über jedes Feedback dazu freuen. Es ist nur ein kleiner Teil meiner Benutzer, aber es ist ein Problem, das ich beheben möchte und über das ich mir keine Sorgen machen möchte. Danke im Voraus.

Außerdem wird meine gesamte Hintergrundarbeit in einer backgroundTask eingerichtet, um zu verhindern, dass Zeitüberschreitungen auftreten. Ich habe keine Probleme mit der Arbeit rund um den Schlüsselbund, aber ich lasse die Dinge nicht weitergehen, bis mein Token gefüllt ist.

BEARBEITEN Ich habe mein Problem mit dem Schlüsselbund herausgefunden, bei dem keine Werte aus dem Hintergrund abgerufen werden. Ich werde die Antwort unten posten und akzeptieren, da ich der Meinung bin, dass diese Frage später für andere wertvoll werden kann.

Bill Burgess
quelle

Antworten:

110

Meine Frage war aus dem Grund nah an der Marke, aber nicht ganz. Nachdem ich Blog für Blog gelesen hatte, Tutorial für Tutorial, fand ich endlich eines, das einen Hinweis darauf gab, was passieren könnte.

Gesperrte Startbildschirme. In den Schlüsselbund-Tutorials wurden die Eingabehilfen für den Schlüsselbund immer leer gelassen, sodass standardmäßig die niedrigste / sicherste Zugriffsebene von Apple verwendet wird. Diese Ebene erlaubt jedoch keinen Schlüsselbundzugriff, wenn der Benutzer einen Passcode auf dem Sperrbildschirm hat. Bingo! Dies erklärt das sporadische Verhalten und warum dies nur einem kleinen Prozentsatz der Benutzer passiert.

Eine Codezeile löst das gesamte Durcheinander.

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

Fügen Sie diese Zeile hinzu, in der ich die Werte für Benutzername und Passwort einstelle. Klappt wunderbar. Hoffe, das wird jemandem da draußen helfen. Es hat mich eine ganze Weile verwirrt, bis ich die Teile zusammensetzen konnte.

Bill Burgess
quelle
1
Vielen Dank! Das war sehr hilfreich.
Rich Waters
3
Wir beschäftigen uns buchstäblich seit Wochen damit. Du bist ein Lebensretter!
OC Rickard
15
Bitte vermeiden Sie, …AccessibleAlwayswenn möglich, oder speichern Sie ein Token, das nur eingeschränkte Berechtigungen bietet (z. B. ein Token, mit dem Sie nach neuen Feed-Elementen lesen, aber nicht posten können). Sie verzichten damit explizit auf eine Verschlüsselungsstufe. Wenn Ihre App bis zur ersten Entsperrung warten kann, ist es möglicherweise am besten, …AfterFirstUnlockIhre Benutzer zu verwenden und anzuweisen, ihre Geräte zuerst zu entsperren.
Millenomi
14
Dies ist eine wirklich schlechte Idee, da diese Anmeldeinformationen nicht mehr geschützt sind. Während etwas mehr Arbeit erforderlich ist, ist es wichtig, einen abgeleiteten Berechtigungsnachweis zu erstellen, der nur für den eingeschränkten Zugriff verwendet werden kann, von dem Sie erwarten, dass er im Hintergrund erforderlich ist, und nicht mehr. Dieser eingeschränkte Berechtigungsnachweis kann nach einiger Zeit abgelaufen sein. Bei jedem Öffnen der App wird ein neuer erstellt, wodurch die alten ungültig werden. Dies schützt den Benutzer, falls der abgeleitete Berechtigungsnachweis kompromittiert wird. Weitere Informationen hierzu finden Sie in der WWDC 2013-Sitzung 204.
Joey Hagedorn
7
Echo @JoeyHagedorn hier - hören Sie die WWDC 2013-Sitzung 204 "Was ist neu bei Multitasking?" um 44:24 Uhr und die WWDC 2013-Sitzung 709 "Schutz der Geheimnisse mit dem Schlüsselbund" um 25:30 Uhr. Sie können den Textinhalt dieser Vorträge auf asciiwwdc.com
Shazron
62

Verwenden Sie kSecAttrAccessibleAfterFirstUnlockanstelle von kSecAttrAccessibleAlways.


Aus Apples Dokumentation :

kSecAttrAccessibleAfterFirstUnlock
Auf die Daten im Schlüsselbundelement kann nach einem Neustart erst zugegriffen werden, wenn das Gerät vom Benutzer einmal entsperrt wurde.

Nach dem ersten Entsperren bleiben die Daten bis zum nächsten Neustart zugänglich. Dies wird für Elemente empfohlen, auf die Hintergrundanwendungen zugreifen müssen. Elemente mit diesem Attribut werden bei Verwendung verschlüsselter Sicherungen auf ein neues Gerät migriert.

Schuss
quelle
4
Diese Antwort sollte ein Kommentar sein ...
Frizlab
Diese Antwort scheint perfekt zu sein, da sie kSecAttrAccessibleAlwaysbereits veraltet ist
Sazzad Hissain Khan
1

In meinem Fall greift watchOS2 auf der iOS-Seite auf Schlüsselbunddaten zu.

Zu Beginn wird kSecAttrAccessibleWhenUnlockedThisDeviceOnly verwendet. Ich kann die Daten lesen, egal ob das iPhone gesperrt ist oder nicht. Es ist sehr verwirrend für mich, dass ich einen Fehler erhalte, wenn watch versucht, auf den Schlüsselbund zuzugreifen :: SecTrustEvaluate [leaf IssuerCommonName SubjectCommonName]

In einigen Fällen wird es zu :: SecOSStatusWith Fehler: [- 25308] Fehler Domain = NSOSStatusErrorDomain Code = -25308 "ks_crypt: e00002e2 konnte den Artikel nicht" oe "(Klasse 6, Tasche: 0) Zugriff auf den Artikel versucht, während der Schlüsselbund gesperrt ist. "" UserInfo = {NSDescription = ks_crypt: e00002e2 konnte den Artikel nicht "oe" (Klasse 6, Tasche: 0) Zugriff auf den Artikel versucht, während der Schlüsselbund gesperrt ist.}

Ich werde meine Antwort aktualisieren, wenn ich mehr Infos bekomme.

Skingtree
quelle