iOS: ¿cómo almacenar nombre de usuario / contraseña dentro de una aplicación?

Tengo una pantalla de inicio de sesión en mi aplicación de iOS. El nombre de usuario y la contraseña se guardarán en NSUserDefaults y se NSUserDefaults nuevamente en la pantalla de inicio de sesión cuando vuelva a ingresar la aplicación (por supuesto, los NSUserDefaults son permanentes).

Ahora, el usuario tiene la posibilidad de desactivar la función de guardar nombre de usuario / contraseña.

Entonces NSUserDefaults se borrará entonces.

Pero en mi aplicación necesito este nombre de usuario / contraseña para las consultas de la base de datos para el usuario. Entonces: ¿Dónde almacenar los datos excepto NSUserDefaults ? (Este lugar puede / debe eliminarse cuando el usuario sale de la aplicación o cierra la sesión).

Siempre debe usar Keychain para almacenar nombres de usuario y contraseñas, y como se almacena de forma segura y solo es accesible para su aplicación, no es necesario eliminarla cuando se cierra la aplicación (si ese era su problema).

Apple proporciona un código de muestra que almacena, lee y elimina elementos de llavero y aquí se explica cómo usar la clase de envoltura de llavero de esa muestra, lo que simplifica enormemente el uso de Keychain.

Incluya Security.framework (en Xcode 3 haga clic derecho en la carpeta de frameworks y agregue el framework existente. En Xcode 4 seleccione su proyecto, luego seleccione el objective, vaya a la pestaña Build Fases y haga clic en + en Link Binary With Files) y KeychainItemWrapper .h &. m archivos en su proyecto, importa el archivo .h donde sea que necesite usar llavero y luego cree una instancia de esta clase:

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

( YourAppLogin puede ser cualquier cosa que elijas para llamar a tu elemento de llavero y puedes tener varios artículos si es necesario)

Luego puede configurar el nombre de usuario y la contraseña usando:

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

Haz que usen:

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

O elimínelos usando:

 [keychainItem resetKeychainItem]; 

Si necesita una versión ARC del contenedor aquí está el enlace https://gist.github.com/1170641 Gracias a

Una solución muy fácil a través de Llaveros .

Es un envoltorio simple para el sistema Keychain. Simplemente agregue los SSKeychain.h , SSKeychain.m , SSKeychainQuery.h SSKeychainQuery.m a su proyecto y agregue Security.framework a su destino.

Para guardar una contraseña:

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

Para recuperar una contraseña:

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

Donde setPassword es qué valor desea guardar y forService es qué variable quiere que se guarde y la cuenta es para qué usuario / objeto es la contraseña y cualquier otra información.

Simplemente puede usar NSURLCredential , guardará tanto el nombre de usuario como la contraseña en el llavero en solo dos líneas de código .

Ver mi respuesta detallada.

Decidí responder cómo usar el llavero en iOS 8 usando Obj-C y ARC.

1) Utilicé el keychainItemWrapper (versión de ARCifief) de GIST: https://gist.github.com/dhoerl/1170641/download – Agregue (+ copie) el KeychainItemWrapper.h y .m a su proyecto

2) Agregue el marco de seguridad a su proyecto (check in project> Build phases> Link binary with Libraries)

3) Agregue la biblioteca de seguridad (#import) y KeychainItemWrapper (#import “KeychainItemWrapper.h”) al archivo .h y .m donde desee utilizar el llavero.

4) Para guardar datos en el llavero:

 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) Leer datos (probablemente la pantalla de inicio de sesión al cargar> 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; 

¡Disfrutar!

Si tiene problemas para recuperar la contraseña utilizando el contenedor de llaveros, use este código:

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

presiona este código de muestra intenté primero el envoltorio de la manzana del código de muestra, pero esto es mucho más simple para mí

Miré usando KeychainItemWrapper (la versión ARC) pero no encontré su contenedor Objective C tan completo como lo deseaba.

Usé esta solución de Kishikawa Katsumi , lo que significaba que escribía menos código y no tenía que usar moldes para almacenar los valores de NSString.

Dos ejemplos de almacenamiento:

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

Dos ejemplos de recuperación

 UICKeyChainStore *store = [UICKeyChainStore keyChainStore]; // or UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:@"YOUR_SERVICE"]; NSString *username = [store stringForKey:@"username"]; NSString *password = [store stringForKey:@"password"]; 

prueba este:

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

puede que ayude

Hay un pequeño error en el código anterior (por cierto Dave fue muy útil para su publicación gracias)

En la parte donde guardamos las credenciales, también necesita el siguiente código para que funcione correctamente.

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

lo más probable es porque la segunda vez que intentamos (re) iniciar sesión con las mismas credenciales, las encuentra ya asignadas en los elementos de llavero y la aplicación se bloquea. con el código anterior, funciona como un amuleto.

Para actualizar esta pregunta:

Para aquellos que utilizan Swift checkout, esta implementación rápida de arrastrar y soltar por Mihai Costea apoya grupos de acceso:

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

Antes de usar el llavero: considere dos veces antes de guardar las contraseñas. En muchos casos, almacenar un token de autenticación (como una ID de sesión de persistencia) y el nombre del correo electrónico o de la cuenta puede ser suficiente. Puede invalidar fácilmente los tokens de autenticación para bloquear el acceso no autorizado, lo que requiere que el usuario vuelva a iniciar sesión en el dispositivo comprometido pero no requiera restablecer la contraseña y tener que volver a iniciar sesión en todos los dispositivos (no solo estamos usando Apple ¿verdad?).

Lo siguiente debería funcionar bien:

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

Pero, ahora puede optar por NURLCredential en lugar de keychain wrapper. Hace lo que tenemos que hacer.

Para swift puedes usar esta biblioteca:

https://github.com/jrendel/SwiftKeychainWrapper

Es compatible con todas las versiones de Swift.