ios - 在 iOS 中将电子邮件/密码保存到钥匙串(keychain)

标签 ios

我是 iOS 开发的新手,如果这是一个新手问题,请原谅我。我的应用程序有一个简单的身份验证机制,它接受用户的电子邮件地址和密码。我还有一个开关,上面写着“记住我”。如果用户打开该开关,我想保留他们的电子邮件/密码,以便将来可以自动填充这些字段。

我已经将它保存到 plist 文件,但我知道这不是最好的主意,因为密码未加密。我找到了一些保存到钥匙串(keychain)的示例代码,但老实说,我有点迷路了。对于下面的函数,我不确定如何调用它以及如何修改它以保存电子邮件地址。

我猜调用它会是:saveString(@"passwordgoeshere");

感谢您的帮助!!!

+ (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);
    }
}

最佳答案

我编写了一个简单的包装器,允许将任何符合 NSCoding 的对象保存到钥匙串(keychain)中。例如,您可以将您的电子邮件和密码存储在 NSDictionary 中,并使用此类将 NSDictionary 存储到钥匙串(keychain)。

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

关于ios - 在 iOS 中将电子邮件/密码保存到钥匙串(keychain),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5247912/

相关文章:

html - 视频自动播放不适用于所有 iPhone

android - Pushbot Android 或 IOS 如何让设备注册特定类型的消息

ios - 在nsarray中搜索最接近的值

ios - CGRect 的表达式不可分配错误

ios - 用于移动支付库的 PayPal AppID

iphone - 指定单元格 imageView 的宽度

ios - 简单的 UIView drawRect 未被调用

iphone - 位置和标题不起作用

ios - 存储用户 token ,如果 token 无效 - 出现登录页面,

ios - 在容器 View Controller 中调整 View 大小