ver usar solicita restablecer quitar protectedcloudkeysyncing olvide mac locales llavero elementos desbloquear cuentas correo contraseñas contraseña ios

ios - usar - restablecer llavero mac



Guardar el correo electrónico/contraseña de Keychain en iOS (2)

Código listo para ARC:

KeychainUserPass.h

#import <Foundation/Foundation.h> @interface KeychainUserPass : NSObject + (void)save:(NSString *)service data:(id)data; + (id)load:(NSString *)service; + (void)delete:(NSString *)service; @end

KeychainUserPass.m

#import "KeychainUserPass.h" @implementation KeychainUserPass + (NSMutableDictionary *)getKeychainQuery:(NSString *)service { return [NSMutableDictionary dictionaryWithObjectsAndKeys: (__bridge id)kSecClassGenericPassword, (__bridge id)kSecClass, service, (__bridge id)kSecAttrService, service, (__bridge id)kSecAttrAccount, (__bridge id)kSecAttrAccessibleAfterFirstUnlock, (__bridge id)kSecAttrAccessible, nil]; } + (void)save:(NSString *)service data:(id)data { NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; SecItemDelete((__bridge CFDictionaryRef)keychainQuery); [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(__bridge id)kSecValueData]; SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL); } + (id)load:(NSString *)service { id ret = nil; NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; [keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData]; [keychainQuery setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; CFDataRef keyData = NULL; if (SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) { @try { ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData]; } @catch (NSException *e) { NSLog(@"Unarchive of %@ failed: %@", service, e); } @finally {} } if (keyData) CFRelease(keyData); return ret; } + (void)delete:(NSString *)service { NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; SecItemDelete((__bridge CFDictionaryRef)keychainQuery); } @end

Soy muy nuevo en el desarrollo de iOS, así que discúlpeme si esta es una pregunta para novatos. Tengo un mecanismo de autenticación simple para mi aplicación que toma la dirección de correo electrónico y la contraseña de un usuario. También tengo un interruptor que dice ''Recordarme''. Si el usuario activa ese interruptor, me gustaría conservar su correo electrónico / contraseña para que esos campos puedan completarse automáticamente en el futuro.

He conseguido que esto funcione al guardar en un archivo plist pero sé que no es la mejor idea ya que la contraseña no está encriptada. Encontré un código de muestra para guardar en el llavero, pero para ser sincero, estoy un poco perdido. Para la función siguiente, no estoy seguro de cómo llamarla y cómo modificarla para guardar también la dirección de correo electrónico.

Supongo que llamarlo sería: saveString(@"passwordgoeshere");

¡¡¡Gracias por cualquier ayuda!!!

+ (void)saveString:(NSString *)inputString forKey:(NSString *)account { NSAssert(account != nil, @"Invalid account"); NSAssert(inputString != nil, @"Invalid string"); NSMutableDictionary *query = [NSMutableDictionary dictionary]; [query setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass]; [query setObject:account forKey:(id)kSecAttrAccount]; [query setObject:(id)kSecAttrAccessibleWhenUnlocked forKey:(id)kSecAttrAccessible]; OSStatus error = SecItemCopyMatching((CFDictionaryRef)query, NULL); if (error == errSecSuccess) { // do update NSDictionary *attributesToUpdate = [NSDictionary dictionaryWithObject:[inputString dataUsingEncoding:NSUTF8StringEncoding] forKey:(id)kSecValueData]; error = SecItemUpdate((CFDictionaryRef)query, (CFDictionaryRef)attributesToUpdate); NSAssert1(error == errSecSuccess, @"SecItemUpdate failed: %d", error); } else if (error == errSecItemNotFound) { // do add [query setObject:[inputString dataUsingEncoding:NSUTF8StringEncoding] forKey:(id)kSecValueData]; error = SecItemAdd((CFDictionaryRef)query, NULL); NSAssert1(error == errSecSuccess, @"SecItemAdd failed: %d", error); } else { NSAssert1(NO, @"SecItemCopyMatching failed: %d", error); } }


Escribí un envoltorio simple que permite guardar cualquier objeto compatible con NSCoding en el llavero. Podría, por ejemplo, almacenar su correo electrónico y contraseña en un NSDictionary y almacenar el NSDictionary en el llavero usando esta clase.

SimpleKeychain.h

#import <Foundation/Foundation.h> @class SimpleKeychainUserPass; @interface SimpleKeychain : NSObject + (void)save:(NSString *)service data:(id)data; + (id)load:(NSString *)service; + (void)delete:(NSString *)service; @end

SimpleKeychain.m

#import "SimpleKeychain.h" @implementation SimpleKeychain + (NSMutableDictionary *)getKeychainQuery:(NSString *)service { return [NSMutableDictionary dictionaryWithObjectsAndKeys: (id)kSecClassGenericPassword, (id)kSecClass, service, (id)kSecAttrService, service, (id)kSecAttrAccount, (id)kSecAttrAccessibleAfterFirstUnlock, (id)kSecAttrAccessible, nil]; } + (void)save:(NSString *)service data:(id)data { NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; SecItemDelete((CFDictionaryRef)keychainQuery); [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData]; SecItemAdd((CFDictionaryRef)keychainQuery, NULL); } + (id)load:(NSString *)service { id ret = nil; NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; [keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; [keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit]; CFDataRef keyData = NULL; if (SecItemCopyMatching((CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) { @try { ret = [NSKeyedUnarchiver unarchiveObjectWithData:(NSData *)keyData]; } @catch (NSException *e) { NSLog(@"Unarchive of %@ failed: %@", service, e); } @finally {} } if (keyData) CFRelease(keyData); return ret; } + (void)delete:(NSString *)service { NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; SecItemDelete((CFDictionaryRef)keychainQuery); } @end