如何使用fmdb登录页面?

时间:2014-01-01 22:37:07

标签: ios sqlite fmdb

我有一个登录页面,其中包含2个用户名和文本字段密码和几个按钮。我想知道如何使用fmdb检查我的数据库中是否存在用户名/密码组合?我还有另一个用于用户注册页面的viewcontroller,有4个用于用户名,密码,电子邮件,联系人号码的文本字段以及一个用于将输入的文本输入数据库的按钮。如何将4个字段中输入的文本保存到数据库中?提前致谢。这是我的代码: 我成功地将数据输入数据库,在registerViewController中,但是如果用户忘记密码和/或用户名,我想在“btnforgot”(忘记密码)操作中输入代码。我在loginViewController中也有所成功,只要检查用户名是否为&密码在数据库中匹配与否相同,但我想我之间缺少一些东西(一些代码)。

LOGINVIEW


#import "loginViewController.h"
#import "carTypeViewController.h"
#import "registerViewController.h"
#import "FMDatabase.h"
#import "AppDelegate.h"
#import "FMDatabaseAdditions.h"
@interface loginViewController ()

@end
@implementation loginViewController
@synthesize lblPass,lblUserName,txtPass,txtUser;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil     {     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];     if(self){         //自定义初始化     }     回归自我;     }

- (void)viewDidLoad

{
self.title = @"Enter Credentials";
username = [[NSMutableArray alloc]init];
password = [[NSMutableArray alloc]init];

[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)btnLogin:(id)sender
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
NSString *path = [docsPath stringByAppendingPathComponent:@"contacts.db"];
FMDatabase *database = [FMDatabase databaseWithPath:path];

[database open];

BOOL success = NO;

    NSInteger count = [database intForQuery:@"select count(*) from RegMembers where USERNAME = ? and PASSWORD = ?", username, password];

if ([txtUser.text length] == 0 || [txtPass.text length]== 0){
    UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Error" message:@"Kindly enter details in all fields" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
    [alert show];
}

else if (count > 0)
{
        success = YES;

        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Welcome" message:@"Login successful" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
        [alert show];

        carTypeViewController *car = [[carTypeViewController alloc]initWithNibName:@"carTypeViewController" bundle:nil];
        [self.navigationController pushViewController:car animated:YES];

}
    else
    {
        UIAlertView *alert1 = [[UIAlertView alloc]initWithTitle:@"Kindly enter the correct credentials" message:@"Entered username or password is incorrect" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
        [alert1 show];

        txtUser.text=@"";
        txtPass.text=@"";
    }
[database close];
}
-(IBAction)removeKeyboard
{
[self.txtUser resignFirstResponder];
[self.txtPass resignFirstResponder];
}

- (IBAction)btnSignUp:(id)sender {
registerViewController *reg = [[registerViewController alloc]initWithNibName:@"registerViewController" bundle:nil];
[self.navigationController pushViewController:reg animated:YES];
}


- (IBAction)btnExit:(id)sender {
exit(1);

}

- (IBAction)btnForgotPass:(id)sender {
}

@end






REGISTERVIEW

- (void)viewDidLoad
{
self.title = @"Create Account";
[super viewDidLoad];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,      NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
NSString *path = [docsPath stringByAppendingPathComponent:@"contacts.db"];
FMDatabase *database = [FMDatabase databaseWithPath:path];

[database open];

[database executeUpdate:@"create table if not exists RegMembers (ID INTEGER NOT NULL     PRIMARY KEY AUTOINCREMENT DEFAULT 0, USERNAME TEXT UNIQUE NOT NULL , PASSWORD TEXT NOT NULL     , EMAIL TEXT NOT NULL , NUMBER TEXT  NOT NULL)"];

[database close];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

-(IBAction)removeKeyboard
{
[self.txtUname resignFirstResponder];
[self.txtPass resignFirstResponder];
[self.txtEmail resignFirstResponder];
[self.txtNumber resignFirstResponder];

}
- (IBAction)btnUAcount:(id)sender
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,     NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
NSString *path = [docsPath stringByAppendingPathComponent:@"contacts.db"];
FMDatabase *database = [FMDatabase databaseWithPath:path];

if ([txtUname.text length] == 0 ||
    [txtPass.text length]== 0   ||
    [txtEmail.text length]== 0  ||
    [txtNumber.text length]== 0)
{
    UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Error" message:@"Kindly     enter details in all fields" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
    [alert show];

}
else

{
    if ([database open])
    {

        [database executeUpdate:@"insert into RegMembers(username, password, email,     number) values(?,?,?,?)",
        [NSString stringWithFormat: @"%@",txtUname.text],[NSString     stringWithFormat:@"%@",txtPass.text],[NSString stringWithFormat:@"%@",txtEmail.text],    [NSString stringWithFormat:@"%@",txtNumber.text],nil];
        if (1)
        {
            NSLog(@"contact added");
            self.txtUname.text = @"";
            self.txtPass.text = @"";
            self.txtEmail.text = @"";
            self.txtNumber.text = @"";
        }
        else
        {
            NSLog(@"failed to add contact");
        }

    }
    [database close];
    UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Registeration succesful"     message:@"Thanks for choosing edmunds" delegate:nil cancelButtonTitle:@"OK"     otherButtonTitles: nil];
    [alert show];
    [self.navigationController popViewControllerAnimated:YES];


}

1 个答案:

答案 0 :(得分:1)

如果要检查用户ID /密码组合是否在数据库中,您可以:

#import "FMDatabaseAdditions"

然后您可以看到用户ID /密码组合是否有资格成功登录:

BOOL success = NO;

NSInteger count = [database intForQuery:@"select count(*) from RegMembers where USERNAME = ? and PASSWORD = ?", username, password];

if (count > 0)
    success = YES;

话虽如此,我还有一些观点,从琐碎到批判:

  1. 现在您总是报告“已添加联系人”。您应该确定插入是否成功。您可以通过检查executeUpdate方法返回的值来执行此操作(如果成功则返回YESNO如果失败则返回INSERT

  2. 使用PRIMARY KEY AUTOINCREMENT密钥时,不应使用DEFAULT 0。首先,我不认为这会完成任何事情(无论如何都会从1开始)。其次,即使它确实如此,使用零也是非常糟糕的,因为调用SQLite lastInsertRowId的FMDB的sqlite3_last_insert_rowid使用零值来表示错误。所以,永远不要使用零。

  3. 更重要的是,您应该永远在未加密的设备上存储密码。 (即使您不关心应用程序的安全性,也有太多用户重新使用密码,因此您需要确保不会成为密码泄密的可能方式。)

    至少,您希望在将密码存储在数据库中时加密密码,然后在登录时加密用户提供的密码,并比较两个加密密码。如果您想查看一些可用的加密服务,请参阅Cryptographic Services Guide

  4. 话虽如此,您甚至可能不想自己编写任何密码加密代码(正确地执行此操作并非完全无关紧要)。

    使用iOS Keychain可能更好。 Apple的主题是WWDC 2013视频Protecting Secrets with the Keychain

    例如,要保存与用户ID相关联的密码,电子邮件地址和号码,您可以执行以下操作:

    // see if the userid already exists
    
    NSDictionary* query = @{(__bridge id)kSecClass       : (__bridge id)kSecClassGenericPassword,
                            (__bridge id)kSecAttrService : @"com.domain.app",
                            (__bridge id)kSecAttrAccount : self.useridTextField.text,
                            (__bridge id)kSecMatchLimit  : (__bridge id)kSecMatchLimitOne,
                            (__bridge id)kSecReturnData  : @NO};
    
    OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL);
    
    if (status == errSecSuccess)
    {
        [[[UIAlertView alloc] initWithTitle:nil message:@"That userid is already registered" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
        return;
    }
    
    // create payload of secret data
    
    NSDictionary *secret = @{@"password" : self.passwordTextField.text ?: [NSNull null],
                             @"email"    : self.emailTextField.text    ?: [NSNull null],
                             @"number"   : self.numberTextField.text   ?: [NSNull null]};
    
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:secret];
    
    // create keychain query
    
    query = @{(__bridge id)kSecClass       : (__bridge id)kSecClassGenericPassword,
              (__bridge id)kSecAttrService : @"com.domain.app",
              (__bridge id)kSecAttrAccount : self.useridTextField.text,
              (__bridge id)kSecValueData   : data};
    
    // add data associated with the userid in the keychain
    
    status = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
    NSAssert(status == errSecSuccess, @"%s: SecItemAdd error: %lu", __FUNCTION__, (unsigned long)status);
    

    然后,当您想要登录时,您可以执行以下操作:

    BOOL success = NO;
    
    NSDictionary* query = @{(__bridge id)kSecClass       : (__bridge id)kSecClassGenericPassword,
                            (__bridge id)kSecAttrService : @"com.domain.app",
                            (__bridge id)kSecAttrAccount : self.useridTextField.text,
                            (__bridge id)kSecMatchLimit  : (__bridge id)kSecMatchLimitOne,
                            (__bridge id)kSecReturnData  : @YES};
    
    CFTypeRef typeRef;
    
    OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &typeRef);
    
    // if we found keychain entry for that userid, check the password
    
    if (status == noErr)
    {
        NSDictionary *dictionary = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)typeRef];
        NSAssert(dictionary, @"%s: unarchiveObjectWithData failed: %@", __FUNCTION__, (__bridge NSData *)typeRef);
        NSString *password = dictionary[@"password"];
        if ([self.passwordTextField.text isEqualToString:password])
            success = YES;
    
        CFRelease(typeRef);
    }
    
    // if we didn't succeed for any reason, tell the user
    
    if (!success)
    {
        [[[UIAlertView alloc] initWithTitle:nil message:@"Login failed" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil] show];
    }