iOS: Wie speichere ich Benutzername / Passwort in einer App?

276

Ich habe einen Anmeldebildschirm in meiner iOS-App. Der Benutzername und das Passwort werden im gespeichert NSUserDefaultsund beim erneuten Aufrufen der App erneut in den Anmeldebildschirm geladen (natürlich NSUserDefaultspermanent).

Jetzt hat der Benutzer die Möglichkeit, die Funktion zum Speichern von Benutzernamen und Passwort zu deaktivieren.

Also NSUserDefaultswird das dann gelöscht.

In meiner App benötige ich diesen Benutzernamen / dieses Passwort jedoch für Datenbankabfragen für den Benutzer. Also: Wo sollen die Daten außer gespeichert werden NSUserDefaults? (Dieser Ort kann / sollte gelöscht werden, wenn der Benutzer die App beendet oder sich abmeldet.)

Kovu
quelle
Der Benutzer kann es nur löschen, indem er entweder das Gerät zurücksetzt oder die App entfernt. Vermisse ich etwas
3
Übrigens, wenn die Daten beim Beenden der App gelöscht werden sollen, warum nicht einfach im RAM aufbewahren?
10
Sie sollten ernsthaft in Betracht ziehen, Schlüsselbund zum Speichern von Benutzernamen und Kennwörtern anstelle von NSUserDefaults zu verwenden.
Filip Radelic
1
Eine grundlegende Vorstellung von der Implementierung von
swift3 erhalten Sie
Bitte sollte ich immer kSecValueData und kSecValueData als Schlüssel verwenden? Oder kann ich eine beliebige Zeichenfolge als Schlüssel verwenden?
Ne AS

Antworten:

424

Sie sollten immer Schlüsselbund verwenden, um Benutzernamen und Kennwörter zu speichern. Da diese sicher gespeichert sind und nur für Ihre App zugänglich sind, müssen Sie sie nicht löschen, wenn die App beendet wird (wenn dies Ihr Anliegen war).

Apple bietet Beispielcode zum Speichern, Lesen und Löschen von Schlüsselbundelementen. Hier erfahren Sie, wie Sie die Schlüsselbund-Wrapper-Klasse aus diesem Beispiel verwenden, was die Verwendung von Schlüsselbund erheblich vereinfacht.

Schließen Sie Security.framework ein (klicken Sie in Xcode 3 mit der rechten Maustaste auf den Ordner "Frameworks" und fügen Sie ein vorhandenes Framework hinzu. Wählen Sie in Xcode 4 Ihr Projekt aus, wählen Sie dann das Ziel aus, wechseln Sie zur Registerkarte "Phasen erstellen" und klicken Sie unter "Binär mit Dateien verknüpfen" auf +) und "KeychainItemWrapper .h &". m Dateien in Ihr Projekt importieren, # die .h-Datei überall dort importieren, wo Sie den Schlüsselbund verwenden müssen, und dann eine Instanz dieser Klasse erstellen:

KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];

( YourAppLogin kann alles sein, was Sie zum Aufrufen Ihres Schlüsselbundartikels ausgewählt haben, und Sie können bei Bedarf mehrere Artikel haben.)

Dann können Sie den Benutzernamen und das Passwort festlegen mit:

[keychainItem setObject:@"password you are saving" forKey:kSecValueData];
[keychainItem setObject:@"username you are saving" forKey:kSecAttrAccount];

Holen Sie sie mit:

NSString *password = [keychainItem objectForKey:kSecValueData];
NSString *username = [keychainItem objectForKey:kSecAttrAccount];

Oder löschen Sie sie mit:

[keychainItem resetKeychainItem];
Filip Radelic
quelle
5
Ich habe meine Antwort mit dem Code und der Beschreibung aktualisiert. Es ist bei weitem nicht so schwer, wie Sie dachten.
Filip Radelic
44
ACHTUNG! Bitte fügen Sie Ihrer Antwort hinzu, dass nur "KeychainItemWrapper kopieren" nicht ausreicht! Ich hatte das Problem, dass ich es danach nicht mehr bauen kann! Sie müssen Ihrem Projekt das security.framework hinzufügen, damit der KeychainItemWrapper funktioniert! (HowTo: Projekt auswählen -> Ziel auswählen -> Registerkarte "Phasen erstellen" auswählen -> "Binär mit Bibliotheken verknüpfen" -> "+" -> Security.Framework hinzufügen)
Kovu
63
Wenn Sie ARC verwenden, wird der Compiler Sie wegen der Verwendung der Konstanten kSecValueDataund kSecAttrAccountdes Objective-C-Codes anschreien. Stellen Sie daher sicher, dass Sie diese mit (__bridge id)z. B. [keychainItem setObject:obj forKey:(__bridge id)kSecValueData];
Joe Hankin am
7
KeychainItemWrapper.m scheint in Zeile 196 einen Speicherverlust zu haben. Ändern der Zeile in "self.keychainItemData = [[[NSMutableDictionary alloc] init] autorelease];" behebt es.
Olof
12
Bei Verwendung von ARC wurde der aktualisierte Code hier von Apple angegeben. Schauen Sie sich Listing 2-1 an. Obwohl der Ansatz der gleiche ist.
Rick
97

Wenn Sie eine ARC-Version des Wrappers benötigen, finden Sie hier den Link https://gist.github.com/1170641 Dank an

Manuel Pintaldi
quelle
Vielen Dank, ich erhalte KeychainItemWrapper .h & .m von dieser URL.
Parthpatel1105
48

Eine sehr einfache Lösung über Schlüsselanhänger .

Es ist ein einfacher Wrapper für das System Keychain. Fügen Sie einfach die SSKeychain.h, SSKeychain.m, SSKeychainQuery.hund SSKeychainQuery.mDateien zu Ihrem Projekt und fügen Sie den Security.framework zu Ihrem Ziel.

So speichern Sie ein Passwort:

[SSKeychain setPassword:@"AnyPassword" forService:@"AnyService" account:@"AnyUser"]

So rufen Sie ein Passwort ab:

NSString *password = [SSKeychain passwordForService:@"AnyService" account:@"AnyUser"];

Wo setPasswordist der Wert, unter dem Sie gespeichert werden möchten, und forServiceunter welcher Variablen soll er gespeichert werden? Das Konto gibt an, für welchen Benutzer / welches Objekt das Kennwort und alle anderen Informationen bestimmt sind.

sust86
quelle
Wissen Sie, wie Sie mit sskeychain Apps mit demselben Benutzernamen und Passwort synchronisieren können?
Joe Shamuraq
4
Wie speichert man neben einem Passwort auch einen Benutzernamen? Wie löscht man ein gesamtes Konto aus der SSKeychain? Beides wird in den Dokumenten nicht erwähnt
user798719
2
Um den Benutzernamen zu erhalten, tun Sie NSString *username = [[SSKeychain accountsForService:@"AnyService"][0] valueForKey:@"acct"]. Dies sollte gut funktionieren, wenn Sie nur ein Konto verwenden. Überprüfen Sie wie immer die Array-Länge, bevor Sie versuchen, auf Index 0 zuzugreifen.
Jared Price
27

Sie können es einfach verwenden NSURLCredential, es speichert sowohl den Benutzernamen als auch das Passwort im Schlüsselbund in nur zwei Codezeilen .

Siehe meine ausführliche Antwort .

Phil
quelle
13

Ich entschied mich zu beantworten, wie man Schlüsselbund in iOS 8 mit Obj-C und ARC verwendet.

1) Ich habe den keychainItemWrapper (ARCifief-Version) von GIST verwendet: https://gist.github.com/dhoerl/1170641/download - Fügen Sie Ihrem Projekt den KeychainItemWrapper.h und .m hinzu (+ kopieren)

2) Fügen Sie Ihrem Projekt das Sicherheitsframework hinzu (überprüfen Sie Projekt> Erstellungsphasen> Binärdatei mit Bibliotheken verknüpfen).

3) Fügen Sie die Sicherheitsbibliothek (#import) und den KeychainItemWrapper (#import "KeychainItemWrapper.h") zur Datei .h und .m hinzu, in der Sie den Schlüsselbund verwenden möchten.

4) So speichern Sie Daten im Schlüsselbund:

NSString *emailAddress = self.txtEmail.text;
NSString *password = self.txtPasword.text;
//because keychain saves password as NSData object
NSData *pwdData = [password dataUsingEncoding:NSUTF8StringEncoding];

//Save item
self.keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];
[self.keychainItem setObject:emailAddress forKey:(__bridge id)(kSecAttrAccount)];
[self.keychainItem setObject:pwdData forKey:(__bridge id)(kSecValueData)];

5) Daten lesen (wahrscheinlich Anmeldebildschirm beim Laden> viewDidLoad):

self.keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];

self.txtEmail.text = [self.keychainItem objectForKey:(__bridge id)(kSecAttrAccount)];

//because label uses NSString and password is NSData object, conversion necessary
NSData *pwdData = [self.keychainItem objectForKey:(__bridge id)(kSecValueData)];
NSString *password = [[NSString alloc] initWithData:pwdData encoding:NSUTF8StringEncoding];
self.txtPassword.text = password;

Genießen!

D_RBD
quelle
11

Wenn Sie Probleme beim Abrufen des Kennworts mithilfe des Schlüsselbund-Wrappers haben, verwenden Sie diesen Code:

NSData *pass =[keychain objectForKey:(__bridge id)(kSecValueData)];
NSString *passworddecoded = [[NSString alloc] initWithData:pass
                                           encoding:NSUTF8StringEncoding];
Robby891
quelle
3

Auschecken dieses Beispielcodes Ich habe zuerst den Wrapper des Apfels aus dem Beispielcode ausprobiert, aber das ist für mich viel einfacher

BSevo
quelle
2

Probier diese:

 KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];
[keychainItem setObject:@"password you are saving" forKey:kSecValueData]; 
[keychainItem setObject:@"username you are saving" forKey:kSecAttrAccount];

möge es helfen.

Vara
quelle
2

Ich habe mir die Verwendung von KeychainItemWrapper (der ARC-Version) angesehen, aber ich fand den Objective C-Wrapper nicht so gesund wie gewünscht.

Ich habe diese Lösung von Kishikawa Katsumi verwendet , was bedeutete, dass ich weniger Code geschrieben habe und keine Casts zum Speichern von NSString-Werten verwenden musste.

Zwei Beispiele für die Speicherung:

[UICKeyChainStore setString:@"kishikawakatsumi" forKey:@"username"];
[UICKeyChainStore setString:@"P455_w0rd$1$G$Z$" forKey:@"password"];

Zwei Beispiele für das Abrufen

UICKeyChainStore *store = [UICKeyChainStore keyChainStore];
    // or
UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:@"YOUR_SERVICE"];

NSString *username = [store stringForKey:@"username"];
NSString *password = [store stringForKey:@"password"];
Carl
quelle
2

Es gibt einen kleinen Fehler im obigen Code (übrigens, Dave, es war sehr hilfreich, deinen Beitrag zu schreiben, danke)

In dem Teil, in dem wir die Anmeldeinformationen speichern, wird außerdem der folgende Code benötigt, um ordnungsgemäß zu funktionieren.

[self.keychainItem setObject:@"myCredentials" forKey:(__bridge id)(kSecAttrService)];

Dies liegt höchstwahrscheinlich daran, dass wir beim zweiten Versuch, uns mit denselben Anmeldeinformationen (erneut) anzumelden, diese bereits in den Schlüsselbundelementen zugewiesen finden und die App abstürzt. Mit dem obigen Code funktioniert es wie ein Zauber.

Wirklichkeit
quelle
2

So aktualisieren Sie diese Frage:

Für diejenigen, die Swift Checkout verwenden, ist diese schnelle Drag & Drop-Implementierung von Mihai Costea, die Zugriffsgruppen unterstützt:

https://github.com/macostea/KeychainItemWrapper.swift/blob/master/KeychainItemWrapper.swift

Vor der Verwendung des Schlüsselbunds: Überlegen Sie zweimal, bevor Sie Kennwörter speichern. In vielen Fällen reicht es möglicherweise aus, ein Authentifizierungstoken (z. B. eine Persistenzsitzungs-ID) und den E-Mail- oder Kontonamen zu speichern. Sie können Authentifizierungstoken leicht ungültig machen, um nicht autorisierten Zugriff zu blockieren. Der Benutzer muss sich erneut auf dem gefährdeten Gerät anmelden, muss jedoch kein Kennwort zurücksetzen und muss sich auf allen Geräten erneut anmelden (wir verwenden nicht nur Apple, oder?).

Pizzamonster
quelle
1

Jetzt können Sie sich für NURLCredential anstelle des Schlüsselbund-Wrappers entscheiden. Es macht das, was wir tun müssen.

Sumitiscreative
quelle
0

Folgendes sollte gut funktionieren:

KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];
[keychainItem setObject:@"password you are saving" forKey:kSecValueData]; 
[keychainItem setObject:@"username you are saving" forKey:kSecAttrAccount];
pkamb
quelle