面试后的一些总结(一)

以前从来没考虑数据安全和加密方面,因为所接触的香港政府项目唯一性很强,要么是指定的小组护士长在用,要么是领导层的查看,以及审核登录,因为打的是企业内部包,所以token和用户名是用NSUserDefaults储存的,当时就没在安全性上深入研究。如果换做银行金融,区块链类App,起码在登录上,还有一些数据处理上就是不合格的。今天就仔细总结归纳一些安全问题:

NSUserDefaults不安全的点

  • 简介: 数据自动保存在沙盒的Libarary/Preferences目录下.

  • 安全隐患:NSUserDefaults其实是plist文件中键值存储,并且最大的问题是存在与沙盒中,这就对安全性埋下了隐患。如果攻击者破解App,拿到了沙盒中的数据,就会造成数据泄漏。当然,一般也不会有把密码直接使用NSUserDefaults存储的,(我token就是这样,年少无知啊)都会进行加密、或者是多重加密后再进行NSUserDefaults存储。这么做其实是可行的,前提是加密算法不能泄漏。

  • 体验上:如果用户删掉App重装的话,之前所有存储的敏感信息都会消失。比如,一个用户误删了使用NSUserDefaults存储密码的App,当重新安装之后,由于以前是记住密码免登录,只因为自己操作不当,接下来要进入找回密码功能,重新修改密码才能再次使用App。这对用户来说是一种相当不友好的体验。

  • 能存储的数据类型为:NSNumber(NSInteger、float、double),NSString,NSDate,NSArray,NSDictionary,BOOL.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
    [userDefault setInteger:1 forKey:@"integer"];
    [userDefault setBool:YES forKey:@"BOOl"];
    [userDefault setFloat:6.5 forKey:@"float"];
    [userDefault setObject:@"123" forKey:@"numberString"];
    NSString *numberString = [userDefault objectForKey:@"numberString"];
    BOOL myBool = [userDefault boolForKey:@"BOOl"];
    [userDefault removeObjectForKey:@"float"];
    [userDefault synchronize];

NSUserDefaults需要注意的:

  • NSUserDefaults存储的数据都是不可变的,想将可变数据存入需要先转为不可变才可以存储.
  • NSUserDefaults是定时把缓存中的数据写入磁盘的,而不是即时写入,为了防止在写完NSUserDefaults后程序退出导致的数据丢失,可
  • 在写入数据后使用synchronize强制立即将数据写入磁盘.

推荐储存:偏好设置和用户信息,如用户名,是否自动登录,字体大小等.

Plist不安全的点

  • 简介: 属性列表(Plist,Property List)是一种结构化的二进制格式文件,包含了内嵌键值对的可执行bundle的基本配置信息。Plist文件主要用于存储App的用户设置及配置信息,例如,游戏类App经常会在Plist文件中存储游戏等级和分数信息。一般来说,App会将存储用户数据的Plist文件保存在“[App home目录]/documents/”目录下。Plist文件可以是XML格式或二进制格式。

  • 安全风险: Plist文件主要用于存储用户设置及App的配置信息,但App可能使用Plist文件存储明文的用户名、密码或其它一些个人敏感信息。而保存在Plist文件中的二进制格式文件数据则可以使用Plist文件编辑器(如plutil)进行查看或修改,即使在一个没有越狱的设备上,plist文件也可以通过工具iExplorer获取。对于以编码、未加密或弱加密形式存储的敏感信息就可能会导致敏感信息泄露了。

读取:

1
2
3
4
5
NSString *plistPath = [[NSBundle mainBundle]pathForResource:@"myTest" ofType:@"plist"];
NSMutableDictionary *dataDic = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath];
/**如果为数组时*/
// NSMutableArray *dataArray = [NSMutableArray arrayWithContentsOfFile:plistPath];
NSLog(@"%@",dataDic);

修改:

1
2
3
4
[dataDic setObject:@"Man" forKey:@"sex"];
[dataDic setObject:@22 forKey:@"age"];
[dataDic writeToFile:plistPath atomically:YES];
NSLog(@"----%@",dataDic);

推荐相对安全的Keychain

Keychain是iOS所提供的一种安全存储参数的方式,最常用来存储账号,密码,用户信息,银行卡资料等信息,Keychain会以加密的方式存储在设备中

优点:

  • 数据并不是放在App的Sanbox,即使删除了App,资料依然保存在keychain中,如果重新安装了App,还可以从keychain中获取数据

  • keychain的数据可以用group的方式,让程序可以在App间共享,不过需要相同的TeamD

  • keychain的数据是经过加密的

    使用keychain时苹果官方已经为我们封装好了文件KeychainItemWrApper,引入即可使用.当然也可是使用其他优秀的第三方的封装,比如ssKeychain,使用方法如下:
    使用方法

沙盒写入

持久化在Document目录下,一般存储非机密数据。
在解决南莲园池项目的多音频文件下载到本地这个需求时我就是采用的沙盒存储。因为这可以极大的节约用户流量,而且也增强了App的体验效果(如果采用在线音频播放,是达不到弱网环境不卡顿且熄屏导航继续播放的目的)

  • Application:存放程序源文件,上架前经过数字签名,上架后不可修改。
  • Documents: 保存应⽤运行时生成的需要持久化的数据,iTunes同步设备时会备份该目录。例如,游戏应用可将游戏存档保存在该目录。
  • tmp:保存应⽤运行时所需的临时数据,使⽤完毕后再将相应的文件从该目录删除。应用没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时不会备份该目录。
  • Library/Caches:保存应用运行时⽣成的需要持久化的数据,iTunes同步设备时不会备份该目录。⼀一般存储体积大、不需要备份的非重要数据,比如网络数据缓存存储到Caches下
  • Library/Preference: 保存应用的所有偏好设置,如iOS的Settings(设置)应⽤会在该目录中查找应⽤的设置信息。iTunes同步设备时会备份该目录。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 获取程序的Home目录       
NSString *path = NSHomeDirectory();

// 获取Document目录
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;

// 获取Cache目录
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;

// 获取Library目录
NSString *path = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES).firstObject;

// 获取Tmp目录
NSString *path = NSTemporaryDirectory();

写入

1
2
3
4
5
6
7
8
9
10
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
NSString *filePath = [path stringByAppendingPathComponent:@"test.txt"];
NSLog(@"%@",filePath);
NSArray *array = @[@"z",@"h",@"y"];
BOOL isSuccess = [array writeToFile:filePath atomically:YES];
if (isSuccess) {
NSLog(@"成功");
} else {
NSLog(@"失败");
}

读取:

1
2
3
4
5
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
NSString *filePath = [path stringByAppendingPathComponent:@"test.txt"];
NSLog(@"%@",filePath);
NSArray *tmpArray = [NSArray arrayWithContentsOfFile:filePath];
NSLog(@"%@",tmpArray);

FMDB

FMDB是iOS平台的SQLite数据库框架,FMDB以OC的方式封装了SQLite的C语言API,使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码,对比苹果自带的Core Data框架,更加轻量级和灵活,提供了多线程安全的数据库操作方法,有效地防止数据混乱。