如何针对登录过程的钥匙串检查/比较文本字段中的值?
Posted
技术标签:
【中文标题】如何针对登录过程的钥匙串检查/比较文本字段中的值?【英文标题】:How to check / a compare value in a text field against a keychain for a login process? 【发布时间】:2012-06-24 01:43:50 【问题描述】:我正在创建一个多用户 iPhone 应用程序,并且我正在尝试完成用户登录过程的编码。我可以成功创建一个帐户,并将用户输入的数据存储到 Core Data DB 中,并将 pin 存储到 Keychain 中,所以现在我正在尝试完成登录过程。下面列出的以下代码是我目前所拥有的,我收到一个错误,No visible @interface for 'Account' 声明选择器'password:'
- (IBAction)processLogin:(id)sender
// hide keyboard
[_textFieldUsername resignFirstResponder];
[_textFieldPin resignFirstResponder];
// First - make activity indicator visible, then start animating, then turn of wrong user / pin label
_welcomeActivityIndicator.hidden = FALSE;
[_welcomeActivityIndicator startAnimating];
[_wrongUserPin setHidden:YES];
// check if username and pin text fields are populated
if ([_textFieldUsername.text length ] == 0 && [_textFieldPin.text length ] == 0)
[_welcomeActivityIndicator stopAnimating];
[_wrongUserPin setHidden:NO];
// CORE DATA
// NSManagedObjectContext *context = _managedObjectContext;
NSFetchRequest *request= [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Account" inManagedObjectContext:_managedObjectContext];
NSPredicate *predicate =[NSPredicate predicateWithFormat:@"username=%@",self.textFieldUsername.text];
// TODO check pin
Account *pinAccount = [[Account alloc] init];
// GETTING ERROR ON BELOW LINE OF CODE! - ERR0R - No visible @interface for 'Account' declares the selector 'password:'
[pinAccount password:_textFieldPin.text];
[request setEntity:entity];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *array = [_managedObjectContext executeFetchRequest:request error:&error];
if (array != nil)
NSUInteger count = [array count]; // may be 0 if the object has been deleted.
NSLog(@"Username may exist, %@",count);
else
NSLog(@"Username does not exist.");
Account 类文件 m 和 h 如下所示:
Account.m
- (NSString*)password
if (self.username)
return [KeychainHelper getPasswordForKey:self.username];
return nil;
- (void)setPassword:(NSString*)aPassword
if (self.username) [KeychainHelper setPassword:aPassword forKey:self.username];
- (void)prepareForDeletion
if (self.username) [KeychainHelper removePasswordForKey:self.username];
@end
Account.h
#import "AccountBase.h"
@interface Account : AccountBase
// nonatomic - don't worry about multithreading
@property (nonatomic, assign) NSString *password;
- (void)setPassword:(NSString*)aPassword;
@end
如果有任何想法或想法,我将不胜感激,并感谢您的阅读。
【问题讨论】:
【参考方案1】:嗯,小错误?使用:
[pinAccount setPassword:_textFieldPin.text];
代替:
[pinAccount password:_textFieldPin.text];
?或者我可能遗漏了什么……
[更新]
您正在调用一个名为 (NSString *)password 的选择器。 您的错误消息说选择器在界面中不可见。 (我认为这意味着您打错了字,实际上是指“setPassword”。)相反,我认为错误在于您的 .h 文件中,(NSString *)password 选择器未在界面中定义,因此任何外部代码都看不到它。 p>
即您可以将此行添加到您的 .h 文件中:
- (NSString *)password;
(我可能会将选择器从 password 重命名为不同的名称,以免与属性混淆。)
【讨论】:
我没有尝试设置密码,因为我在创建帐户时会这样做。我正在尝试将输入到文本字段中的密码与存储在钥匙串中的密码进行检查,以创建/完成登录过程。 哦,我明白你在说什么。基于此,看起来您在 .m 文件中定义了一个名为 (NSString *)password 的选择器,但它没有在 .h 文件中声明。这也可以解释您的错误消息。我会更新答案。【参考方案2】:我能够使用以下代码检查/验证 pin。
// CORE DATA
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Account" inManagedObjectContext:_managedObjectContext];
// set entity for request
[request setEntity:entity];
// filter results using a predicate
NSPredicate *pred =[NSPredicate predicateWithFormat:(@"username = %@"), _textFieldUsername.text];
// set predicate for the request
[request setPredicate:pred];
NSError *error = nil;
// store DB usernames in results array
NSArray *results = [_managedObjectContext executeFetchRequest:request error:&error];
NSLog(@"The returned results are %@",results);
// check text field against results stored in DB
for (Account *anAccount in results)
if ([anAccount.username isEqualToString:_textFieldUsername.text])
NSLog(@"Your username exists");
if ([anAccount.password isEqualToString:_textFieldPin.text])
NSLog(@"Your pin is correct");
【讨论】:
看起来您将凭据存储在数据库中。不确定这是否安全。您可能应该查看 Apple 提供的 KeychainItemWrapper 示例代码。 (developer.apple.com/library/ios/#samplecode/GenericKeychain/…)【参考方案3】:它没有调用 Account.h 接口中声明的方法。而[pinAccount password:_textFieldPin.text];
正在调用一个与 Account 的属性共享同名的函数,即该属性的 getter。
【讨论】:
以上是关于如何针对登录过程的钥匙串检查/比较文本字段中的值?的主要内容,如果未能解决你的问题,请参考以下文章
Keychainitemwrapper 类中的 SecItemCopyMatching 条件失败,因此无法检索钥匙串中保存的值