iOS 使用Keychain保存用户帐号及密码

一、什么是Keychain

1. iOS设备中的Keychain是一个安全的存储容器.
2. 它可以用来为不同应用保存敏感信息比如用户名,密码,网络密码,认证令牌等等。
3. 它是一个sqlite数据库,文件路径为:/private/var/Keychains/keychain-2.db,其保存的所有数据都是加密过的。
4. 通过keychain access groups可以在应用之间共享keychain中的数据。要使用共享数据就需要在我们保存数据到keychain的时候指定group
5. 而把数据保存到keychain的最好方法就是用苹果提供的KeychainItemWrapper,后面会提到。
就我目前所用的App中使用Keychain的典型App就是百度云,大家可以自行下载看看效果。

二、为什么使用Keychain而不是NSUserDefaults

  1. 开发者通常会希望能够利用操作系统提供的功能来保存凭证(Credentials),而不是把它们保存到NSUserDefaults,plist文件等地方。
    保存这些数据的原因是开发者为了避免让用户每次登录都需要输入帐号密码等繁琐的操作,得到良好的用户体验,因此会把用户相关信息保存到设备上的某个地方,并且在用户再次打开应用的时候用App会使用这些数据进行自动登录。
  2. Keychain的信息是存在于每个应用(app)的沙盒之外的。也就是说Keychain里保存的信息不会因App被删除而丢失,在用户重新安装App后依然有效,这是Keychain相对于NSUserDefaults的优点。
  3. 另外,NSUserDefaults将用户帐号信息保存到plist表中,如果不加入繁琐的加密方式(一般使用md5加密)保存的话,当你的sandbox被破解,或者你的手机被越狱,那么他人就能轻松拿到这个文件,并读取到存储的信息,用户信息就会变得不安全,具体的大家可以参考这篇文章:
    为什么直接把密码存储在NSUserDefaults中不安全?

三、简单使用

  1. 创建一个NSObject类文件,类名一般形式为工程明的英文缩写+Keychain


    iOS 使用Keychain保存用户帐号及密码_第1张图片
    创建类文件
  2. 在Keychain头文件中#import 并创建存储、读取、删除三个类方法


    iOS 使用Keychain保存用户帐号及密码_第2张图片
    KeyChain头文件
  3. 在.m中实现三个类方法
    3.1 创建一个查询字典,格式是NSMutableDictionary,需要配置的内容下次再分析,功能就相当于写一句SQL一样
    + (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
    return [NSMutableDictionary dictionaryWithObjectsAndKeys:
    (__bridge id)kSecClassGenericPassword,(id)kSecClass,// 标识符(kSecAttrGeneric通常值位密码)
    service, (__bridge id)kSecAttrService,// 服务(kSecAttrService)
    service, (__bridge id)kSecAttrAccount,// 账户(kSecAttrAccount)
    (__bridge id)kSecAttrAccessibleAfterFirstUnlock,(__bridge id)kSecAttrAccessible,// kSecAttrAccessiblein变量用来指定这个应用何时需要访问这个数据
    nil];
    }
    3.2 添加数据
    + (void)addKeychainData:(id)data forKey:(NSString *)key {
    // 获取查询字典
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:key];
    // 在删除之前先删除旧数据
    SecItemDelete((__bridge CFDictionaryRef)keychainQuery);
    // 添加新的数据到字典
    [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(__bridge id)kSecValueData];
    // 将数据字典添加到钥匙串
    SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL);
    }
    3.3 获取数据
    + (id)getKeychainDataForKey:(NSString *)key {
    id ret = nil;
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:key];

        [keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
        [keychainQuery setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
        CFDataRef keyData = NULL;
        if (SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
     @try {
           ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
       } @catch (NSException *e) {
           NSLog(@"Unarchive of %@ failed: %@",key,e);
       } @finally {
    
       }
      }
    
      if (keyData) {
          CFRelease(keyData);
      }
    
      return ret;
    }
    

3.4 删除数据
+ (void)deleteKeychainDataForKey:(NSString *)key {
NSMutableDictionary *keychainQuery = [self getKeychainQuery:key];
SecItemDelete((__bridge CFDictionaryRef)keychainQuery);
}

Demo:https://github.com/StruggleForever/Keychain
参考链接:http://my.oschina.net/w11h22j33/blog/206713
参考链接:http://www.cnblogs.com/rayshen/p/5072850.html

你可能感兴趣的:(iOS 使用Keychain保存用户帐号及密码)