用户名和密码将保存在
NSUserDefaults
中,并在再次进入该应用程序时再次加载到登录屏幕中(当然,NSUserDefaults
是永久的)。现在,用户可以禁用用户名/密码保存功能。
因此
NSUserDefaults
将被清除。但是在我应用程序我需要此用户名/密码来进行用户数据库查询。
所以:除
NSUserDefaults
之外,数据存储在哪里? (当用户退出应用或注销时,可以/应该删除此地方)。
#1 楼
您应该始终使用钥匙串来存储用户名和密码,并且由于它安全地存储并且只能由您的应用访问,因此在应用退出时无需删除它(如果您对此感到担忧)。Apple提供存储,读取和删除钥匙串项目的示例代码,这是如何使用该示例中的钥匙串包装器类,从而大大简化了使用钥匙串的过程。
包括Security.framework(在Xcode 3中,右键单击在Xcode 4中选择您的项目,然后选择目标,转到Build Phases选项卡,然后单击Link Binary With Files下的+,然后将KeychainItemWrapper .h和.m文件导入您的项目,#import .h文件任何需要使用钥匙串然后创建此类的实例的地方:
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];
(YourAppLogin可以是您选择调用钥匙串项的任何项,并且可以有多个项
然后可以使用以下命令设置用户名和密码:
q4312 078q
使用以下方法获取它们:
[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];
评论
我已经用代码和说明更新了答案。这并不像您想的那么难。
–Filip Radelic
11年8月7日在11:18
吸引力!请补充您的答案,仅“复制KeychainItemWrapper”是不够的!我有一个问题,那就是以后无法构建!您必须将security.framework添加到KeychainItemWrapper可以使用的项目中! (操作方法:选择项目->选择目标->选择选项卡“构建阶段”->选择“使用库链接二进制文件”->“ +”->添加Security.Framework)
– PassionateDeveloper
2011年8月7日在17:20
使用ARC时,编译器会对在Objective-C代码中使用常量kSecValueData和kSecAttrAccount喊叫您,因此请务必使用(__bridge id)强制转换它们,例如[keychainItem setObject:obj forKey:(__ bridge id)kSecValueData] ;
–乔·汉金(Joe Hankin)
13-4-6在23:13
KeychainItemWrapper.m似乎在第196行出现内存泄漏。将该行更改为“ self.keychainItemData = [[[[NSMutableDictionary alloc] init] autorelease];”。解决它。
–牛头
2013年6月17日12:33
使用ARC时,Apple已在此处提供了更新的代码。看清单2-1。虽然方法是相同的。
–里克
2014年8月26日12:35
#2 楼
如果您需要ARC版本的包装器,请点击以下链接https://gist.github.com/1170641感谢
评论
谢谢,我从该URL获得KeychainItemWrapper .h和.m。
–Parthpatel1105
18年1月29日在2:46
#3 楼
通过钥匙串非常简单的解决方案。它是系统钥匙串的简单包装。只需将
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
是要保存在其下的变量,帐户是针对哪个用户的/ object密码和其他任何信息。评论
您知道如何使用sskeychain来同步具有相同用户名和密码的应用程序吗?
– Joe Shamuraq
13年3月27日在16:36
除了密码,您还如何存储用户名?如何从SSKeychain删除整个帐户?两者都没有提到文档
–user798719
2013年9月9日18:57
要获取用户名,请执行NSString * username = [[SSKeychain accountsForService:@“ AnyService”] [0] valueForKey:@“ acct”]。如果您仅使用一个帐户,这应该可以正常工作。与往常一样,请确保在尝试访问索引0之前检查数组长度。
–讨厌的价格
2014年6月12日下午16:26
#4 楼
您只需使用NSURLCredential
,它只需两行代码即可将用户名和密码保存在钥匙串中。请参阅我的详细答案。
#5 楼
我决定回答如何使用Obj-C和ARC在iOS 8中使用钥匙串。1)我使用了GIST的keychainItemWrapper(ARCifief版本):
https://gist.github .com / dhoerl / 1170641 / download
-将KeychainItemWrapper.h和.m添加(+复制)到您的项目中
2)将Security框架添加到您的项目中(在项目中签入>构建阶段>使用库链接二进制文件)
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;
享受吧!
#6 楼
如果您在使用钥匙串包装器检索密码时遇到问题,请使用以下代码:NSData *pass =[keychain objectForKey:(__bridge id)(kSecValueData)];
NSString *passworddecoded = [[NSString alloc] initWithData:pass
encoding:NSUTF8StringEncoding];
#7 楼
检出此示例代码我首先尝试了示例代码中的苹果包装纸,但这对我来说要简单得多
#8 楼
试试这个: KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];
[keychainItem setObject:@"password you are saving" forKey:kSecValueData];
[keychainItem setObject:@"username you are saving" forKey:kSecAttrAccount];
可能会有所帮助。
#9 楼
我看过使用KeychainItemWrapper(ARC版本),但没有找到理想的目标C包装器。我使用Kishikawa Katsumi的此解决方案,这意味着我编写了更少的代码,而没有不必使用强制转换来存储NSString值。
两个存储示例:
[UICKeyChainStore setString:@"kishikawakatsumi" forKey:@"username"];
[UICKeyChainStore setString:@"P455_w0rd$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 楼
上面的代码中有一个小错误(顺便说一句,戴夫对您的帖子非常有帮助,谢谢您)在保存凭据的部分中,它还需要以下代码才能正常工作。
[self.keychainItem setObject:@"myCredentials" forKey:(__bridge id)(kSecAttrService)];
最可能是因为我们第二次尝试使用相同的凭据登录(重新),发现它们已在钥匙串项中分配,并且应用程序崩溃。使用上面的代码,它就像一个魅力。
#11 楼
要更新此问题:对于那些使用Swift签出的用户,Mihai Costea支持访问组的拖放式swift实现:
https://github.com/macostea/KeychainItemWrapper .swift / blob / master / KeychainItemWrapper.swift
在使用钥匙串之前:
在存储密码之前要考虑两次。在许多情况下,存储身份验证令牌(例如持久性会话ID)以及电子邮件或帐户名可能就足够了。您可以轻松地使身份验证令牌无效,以阻止未经授权的访问,这要求用户再次在受感染的设备上登录,而又不需要重置密码,而必须在所有设备上再次登录(我们不仅使用Apple,还使用Apple吗?)。
#12 楼
但是,现在您可以使用NURLCredential而不是钥匙串包装器了。它完成了我们需要做的。#13 楼
对于swift,您可以使用以下库:https://github.com/jrendel/SwiftKeychainWrapper
它支持swift的所有版本。
#14 楼
以下应该可以正常工作:KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];
[keychainItem setObject:@"password you are saving" forKey:kSecValueData];
[keychainItem setObject:@"username you are saving" forKey:kSecAttrAccount];
评论
用户只能通过重置设备或删除应用程序来清除它。我想念什么吗?顺便说一句,如果用户退出应用程序时应该删除数据,为什么不只是将其保存在RAM中?
您应该认真考虑使用Keychain而不是NSUserDefaults来存储用户名和密码。
您可以从此处获得关于swift3实现的基本想法
请问我应该始终使用kSecValueData和kSecValueData作为键吗?还是可以将任何字符串用作键?