首页 文章

iOS:如何在应用程序中存储用户名/密码?

提问于
浏览
265

我的iOS应用程序中有一个登录屏幕 . 用户名和密码将保存在 NSUserDefaults 中,并在您再次进入应用程序时再次加载到登录屏幕中(当然, NSUserDefaults 是永久性的) .

现在,用户可以禁用用户名/密码保存功能 .

那么 NSUserDefaults 将被清除 .

但在我的应用程序中,我需要这个用户名/密码用于用户的数据库查询 . 那么:除了 NSUserDefaults 之外,哪里存储数据? (当用户退出应用程序或注销时,可以/应该删除此位置) .

14 回答

  • 0

    您应该始终使用Keychain来存储用户名和密码,并且由于它是安全存储的,并且只能由您的应用访问,因此无需在应用退出时删除它(如果这是您关注的话) .

    Apple提供了sample code来存储,读取和删除钥匙串项目,以下是如何使用该示例中的钥匙串包装类,这大大简化了使用Keychain .

    包括Security.framework(在Xcode 3中右键单击frameworks文件夹并添加现有框架 . 在Xcode 4中选择你的项目,然后选择target,转到Build Phases选项卡,然后单击Link Binary With Files下)和KeychainItemWrapper .h&.m将文件放入项目中,#导入.h文件,无论您需要使用钥匙串,然后创建此类的实例:

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

    (YourAppLogin可以是您选择调用钥匙串项目的任何内容,如果需要,您可以拥有多个项目)

    然后您可以使用以下命令设置用户名和密码:

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

    让他们使用:

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

    或使用以下方法删除它

    [keychainItem resetKeychainItem];
    
  • 1

    如果您需要ARC版本的包装器,请链接https://gist.github.com/1170641谢谢

  • 96

    通过Keychains非常简单的解决方案 .

    它是系统Keychain的简单包装器 . 只需将 SSKeychain.hSSKeychain.mSSKeychainQuery.hSSKeychainQuery.m 文件添加到项目中,然后将Security.framework添加到目标 .

    要保存密码:

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

    要检索密码:

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

    其中 setPassword 是您想要保存的值, forService 是您想要保存的变量,而帐户是用于密码和任何其他信息的用户/对象 .

  • -1

    你可以简单地使用 NSURLCredential ,它将 save both username and password in the keychain in just two lines of code .

    请参阅我的详细answer .

  • 2

    我决定使用Obj-C和ARC回答如何在iOS 8中使用keychain .

    1)我使用了GIST的keychainItemWrapper(ARCifief版本):https://gist.github.com/dhoerl/1170641/download - 将KeychainItemWrapper.h和.m添加(复制)到您的项目中

    2)将安全框架添加到您的项目中(签入项目>构建阶段>使用库链接二进制文件)

    3)将安全库(#import)和KeychainItemWrapper(#import“KeychainItemWrapper.h”)添加到要使用钥匙串的.h和.m文件中 .

    4)将数据保存到钥匙串:

    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)读取数据(可能是加载时的登录屏幕> 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;
    

    请享用!

  • 1

    如果您在使用钥匙串包装器检索密码时遇到问题,请使用以下代码:

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

    checkout this sample code我首先尝试了示例代码中的apple的包装,但这对我来说简单得多

  • 47

    我查看了使用KeychainItemWrapper(ARC版本),但我发现它的Objective C包装器并不像所希望的那样 Health .

    我使用了this solution Kishikawa Katsumi,这意味着我写了更少的代码,并且不必使用强制转换来存储NSString值 .

    两个存储示例:

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

    检索的两个例子

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

    试试这个:

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

    可能会有所帮助 .

  • 1

    上面的代码中有一个小错误(顺便说一句,Dave对你的帖子非常有帮助,谢谢你)

    在我们保存凭据的部分中,它还需要以下代码才能正常工作 .

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

    最有可能是因为我们第二次尝试(重新)使用相同的凭据登录,它发现它们已经在钥匙串项目中分配,并且应用程序崩溃 . 使用上面的代码,它就像一个魅力 .

  • 0

    要更新此问题:

    对于那些使用Swift结账的人来说,Mihai Costea支持访问组的拖放快速实施:

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

    在使用钥匙串之前:在存储密码之前考虑两次 . 在许多情况下,存储身份验证令牌(例如持久性会话ID)和电子邮件或帐户名称可能就足够了 . 您可以轻松地使身份验证令牌无效以阻止未经授权的访问,要求用户再次登录受感染的设备但不需要重置密码并且必须在所有设备上再次登录(我们不仅仅使用Apple吗?) .

  • 414

    但是,现在你可以使用NURLCredential而不是keychain包装器 . 它做我们需要做的事情 .

  • 12

    对于swift,您可以使用此库:

    https://github.com/jrendel/SwiftKeychainWrapper

    它支持所有版本的swift .

  • 2

    以下应该工作得很好:

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

相关问题