J'ai un écran de connexion dans mon application iOS. Le nom d'utilisateur et le mot de passe seront enregistrés dans la NSUserDefaults
et seront à nouveau chargés dans l'écran de connexion lorsque vous entrez de nouveau dans l'application (bien entendu, NSUserDefaults
sont permanents).
Désormais, l’utilisateur a la possibilité de désactiver la fonction de sauvegarde du nom d’utilisateur/mot de passe.
Ainsi, la NSUserDefaults
sera effacée à ce moment-là.
Mais dans mon application, j'ai besoin de ce nom d'utilisateur/mot de passe pour les requêtes de base de données de l'utilisateur. Donc: Où stocker les données sauf NSUserDefaults
? (Cet endroit peut/doit être supprimé lorsque l'utilisateur quitte l'application ou se déconnecte).
Vous devez toujours utiliser Keychain pour stocker les noms d'utilisateur et les mots de passe. Comme il est stocké de manière sécurisée et uniquement accessible pour votre application, il n'est pas nécessaire de le supprimer à la fermeture de l'application (si cela vous concernait).
Apple fournit exemple de code qui stocke, lit et supprime les éléments du trousseau. Voici comment utiliser la classe wrapper de trousseau de cet exemple, ce qui simplifie grandement l'utilisation de Trousseau.
Incluez Security.framework (dans Xcode 3, cliquez avec le bouton droit de la souris sur le dossier frameworks et ajoutez un framework existant. Dans Xcode 4, sélectionnez votre projet, sélectionnez cible, accédez à l’onglet Build Phases et cliquez sur + sous Link Binary Avec les fichiers) et les fichiers KeychainItemWrapper .h & .m dans votre projet, importez le fichier .h partout où vous devez utiliser un trousseau, puis créez une instance de cette classe:
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];
( YourAppLogin peut être ce que vous avez choisi d'appeler votre élément de trousseau et vous pouvez avoir plusieurs éléments si nécessaire)
Ensuite, vous pouvez définir le nom d'utilisateur et le mot de passe en utilisant:
[keychainItem setObject:@"password you are saving" forKey:kSecValueData];
[keychainItem setObject:@"username you are saving" forKey:kSecAttrAccount];
Obtenez-les en utilisant:
NSString *password = [keychainItem objectForKey:kSecValueData];
NSString *username = [keychainItem objectForKey:kSecAttrAccount];
Ou supprimez-les en utilisant:
[keychainItem resetKeychainItem];
Si vous avez besoin d’une version ARC du wrapper, voici le lien https://Gist.github.com/1170641 Merci à
Une solution très facile via Keychains .
C'est un simple emballage pour le trousseau système. Ajoutez simplement les fichiers SSKeychain.h
, SSKeychain.m
, SSKeychainQuery.h
et SSKeychainQuery.m
à votre projet et ajoutez le Security.framework à votre cible.
Pour enregistrer un mot de passe:
[SSKeychain setPassword:@"AnyPassword" forService:@"AnyService" account:@"AnyUser"]
Pour récupérer un mot de passe:
NSString *password = [SSKeychain passwordForService:@"AnyService" account:@"AnyUser"];
Où setPassword
est la valeur que vous souhaitez enregistrer et forService
, la variable sous laquelle vous souhaitez l'enregistrer. Le compte correspondant à l'utilisateur/à l'objet, le mot de passe et toute autre information.
Vous pouvez simplement utiliser NSURLCredential
, il enregistrera le nom d'utilisateur et le mot de passe du trousseau en seulement deux lignes de code .
Voir mon détaillé réponse .
J'ai décidé de répondre à l'utilisation du trousseau dans iOS 8 à l'aide d'Obj-C et d'ARC.
1) J'ai utilisé le keychainItemWrapper (version ARCifief) de Gist: https://Gist.github.com/dhoerl/1170641/download - Ajoutez (+ copiez) le KeychainItemWrapper.h et .m à votre projet
2) Ajoutez le cadre de sécurité à votre projet (archivez projet> phases de construction> lien binaire avec bibliothèques).
3) Ajoutez la bibliothèque de sécurité (#import) et KeychainItemWrapper (#import "KeychainItemWrapper.h") au fichier .h et .m où vous souhaitez utiliser le trousseau.
4) Pour enregistrer les données dans le trousseau:
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) Lire les données (écran de connexion probablement lors du chargement> 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;
Prendre plaisir!
Si vous rencontrez un problème lors de la récupération du mot de passe à l'aide du wrapper du trousseau, utilisez ce code:
NSData *pass =[keychain objectForKey:(__bridge id)(kSecValueData)];
NSString *passworddecoded = [[NSString alloc] initWithData:pass
encoding:NSUTF8StringEncoding];
checkout this exemple de code j’ai essayé d’abord le wrapper d’Apple à partir de l’exemple de code mais c’est beaucoup plus simple pour moi
essaye celui-là:
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];
[keychainItem setObject:@"password you are saving" forKey:kSecValueData];
[keychainItem setObject:@"username you are saving" forKey:kSecAttrAccount];
peut aider.
Pour mettre à jour cette question:
Pour ceux qui utilisent Swift checkout, effectuez ce glisser-déposer Swift implémenté par Mihai Costea prenant en charge les groupes d'accès:
https://github.com/macostea/KeychainItemWrapper.Swift/blob/master/KeychainItemWrapper.Swift
Avant d’utiliser le trousseau: réfléchissez bien avant de stocker les mots de passe. Dans de nombreux cas, stocker un jeton d'authentification (tel qu'un identifiant de session de persistance) et le nom de messagerie ou du compte peut suffire. Vous pouvez facilement invalider des jetons d'authentification pour bloquer les accès non autorisés, ce qui oblige l'utilisateur à se connecter à nouveau sur le périphérique compromis, mais ne nécessite pas de réinitialisation du mot de passe et doit se connecter à nouveau sur tous les périphériques (nous n'utilisons pas seulement Apple? ).
J'ai envisagé d'utiliser KeychainItemWrapper (la version ARC) mais je n'ai pas trouvé son wrapper Objective C aussi sain que souhaité.
J'ai utilisé cette solution par Kishikawa Katsumi , ce qui voulait dire que je rédigeais moins de code et que je n'avais pas à utiliser de transtypage pour stocker les valeurs NSString.
Deux exemples de stockage:
[UICKeyChainStore setString:@"kishikawakatsumi" forKey:@"username"];
[UICKeyChainStore setString:@"P455_w0rd$1$G$Z$" forKey:@"password"];
Deux exemples de récupération
UICKeyChainStore *store = [UICKeyChainStore keyChainStore];
// or
UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:@"YOUR_SERVICE"];
NSString *username = [store stringForKey:@"username"];
NSString *password = [store stringForKey:@"password"];
Il y a un petit bug dans le code ci-dessus (en passant, Dave était très utile, votre message merci)
Dans la partie où nous sauvegardons les informations d'identification, le code suivant est également nécessaire pour fonctionner correctement.
[self.keychainItem setObject:@"myCredentials" forKey:(__bridge id)(kSecAttrService)];
très probablement, c'est parce que la deuxième fois que nous essayons de (re) connecter avec les mêmes informations d'identification, nous les trouvons déjà attribués dans les éléments de trousseau et l'application se bloque. avec le code ci-dessus cela fonctionne comme un charme.
Mais maintenant, vous pouvez opter pour NURLCredential au lieu de l’enveloppe du trousseau. Il fait ce que nous devons faire.
Pour Swift, vous pouvez utiliser cette bibliothèque:
https://github.com/jrendel/SwiftKeychainWrapper
Il supporte toutes les versions de Swift.
Ce qui suit devrait bien fonctionner:
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];
[keychainItem setObject:@"password you are saving" forKey:kSecValueData];
[keychainItem setObject:@"username you are saving" forKey:kSecAttrAccount];