iOS:如何在应用程序中存储用户名/密码?
我在iOS应用程序中有一个login屏幕。 用户名和密码将被保存在NSUserDefaults中,当你再次进入应用程序时(当然,NSUserDefaults是永久性的),将再次加载到login屏幕。
现在,用户有可能禁用用户名/密码保存function。
那么NSUserDefaults将被清除。
但在我的应用程序中,我需要用户名/密码进行数据库查询。 那么:除了NSUserDefaults之外,在哪里存储数据呢? (当用户退出应用程序或注销时,可以/应该删除此地点)。
您应该始终使用钥匙串存储用户名和密码,并且由于它安全地存储并且只能被您的应用程序访问,所以在应用程序退出时(如果您担心的话),不需要将其删除。
Apple提供了存储,读取和删除钥匙串项目的示例代码 ,以下是如何使用该示例中的钥匙串包装类,这大大简化了使用钥匙串。
包括Security.framework (在Xcode 3中,右键单击框架文件夹并添加现有的框架,在Xcode 4中select你的项目,然后select目标,进入Build Phases选项卡并点击Link Binary With Files)和KeychainItemWrapper .h&。 m文件导入到您的项目中,#导入.h文件,无论您需要使用钥匙串,然后创build此类的实例:
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];
(您的应用程序login可以是任何你select调用你的钥匙链项目,如果需要可以有多个项目)
然后您可以使用以下设置用户名和密码:
[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];
如果你需要一个ARC版本的包装,这里是链接https://gist.github.com/1170641感谢;
通过钥匙链的一个非常简单的解决scheme。
这是系统钥匙串的简单包装。 只需将SSKeychain.h
, SSKeychain.m
, SSKeychainQuery.h
和SSKeychainQuery.m
文件添加到您的项目并将Security.framework添加到您的目标。
保存密码:
[SSKeychain setPassword:@"AnyPassword" forService:@"AnyService" account:@"AnyUser"]
取回密码:
NSString *password = [SSKeychain passwordForService:@"AnyService" account:@"AnyUser"];
其中setPassword
是你想要保存的值, forService
是你希望保存的variables,account是用户/对象的密码和其他信息。
你可以简单的使用NSURLCredential
,它只需要在两行代码中保存钥匙串中的用户名和密码 。
看到我的详细答案 。
如果您在使用钥匙串包装器检索密码时遇到问题,请使用以下代码:
NSData *pass =[keychain objectForKey:(__bridge id)(kSecValueData)]; NSString *passworddecoded = [[NSString alloc] initWithData:pass encoding:NSUTF8StringEncoding];
我决定回答如何使用Obj-C和ARC在iOS 8中使用钥匙串。
1)我使用了GIST的keychainItemWrapper(ARCifief版本): https ://gist.github.com/dhoerl/1170641/download – 将KeychainItemWrapper.h和.m添加(+复制)到您的项目
2)将安全框架添加到您的项目中(签入项目>构build阶段>与库链接二进制文件)
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)读取数据(可能login屏幕上加载> 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;
请享用!
结帐这个示例代码,我试着先从示例代码的苹果包装,但这对我来说简单得多
我看着使用KeychainItemWrapper(ARC版本),但我没有find它的目标C包装作为健康所需。
我使用Kishikawa Katsumi的 这个解决scheme ,这意味着我写了更less的代码,并且不必使用强制转换来存储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"];
试试这个:
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil]; [keychainItem setObject:@"password you are saving" forKey:kSecValueData]; [keychainItem setObject:@"username you are saving" forKey:kSecAttrAccount];
可能会有所帮助。
在上面的代码中有一个小错误(顺便说一下,Dave对你的post非常有帮助,谢谢)
在我们保存凭据的部分,为了正常工作,还需要下面的代码。
[self.keychainItem setObject:@"myCredentials" forKey:(__bridge id)(kSecAttrService)];
最有可能是因为我们第二次尝试(重新)使用相同的凭据login,发现它们已经分配到钥匙串项目和应用程序崩溃。 与上面的代码,它的作品就像一个魅力。
要更新这个问题:
对于那些使用Swift checkout的人来说,这个由Mihai Costea实现的快速实现支持访问组:
https://github.com/macostea/KeychainItemWrapper.swift/blob/master/KeychainItemWrapper.swift
在使用钥匙串之前:在存储密码之前考虑两次。 在许多情况下,存储身份validation令牌(如持久性会话ID)和电子邮件或帐户名称可能就足够了。 您可以很容易地使身份validation令牌无效,以阻止未经授权的访问,要求用户再次login受感染的设备,但不需要重置密码,并且需要在所有设备上重新login(我们不只是使用苹果公司)。
以下应该工作得很好:
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil]; [keychainItem setObject:@"password you are saving" forKey:kSecValueData]; [keychainItem setObject:@"username you are saving" forKey:kSecAttrAccount];
但是,现在你可以去NURLCredential而不是钥匙串包装。 它做我们需要做的事情。