iOS本地数据存储

一、先写总结建议

        ● 一般不涉及客户隐私和密码的数据,在本地使用NSUserDefaults 进行存储

        ● 当牵扯到用户隐私和密码的数据时,建议在存储前使用一定的算法进行加密,在使用时,同样适用相应的算法进行解密

        ● 涉及用户隐私和密码的数据建议使用keychain 进行本地的数据存储

        ● 本地避免敏感数据的存储

        ● 在app每一次和服务器进行数据的交互的时候,涉及到敏感数据的时候,客户端和服务器数据通讯时进行RSA+MD5  的加解密,防止第三方的破解

二、常用的一些 存储方式

        1、plist

                ● 是一种结构化的二进制格式文件,包含了内嵌键值对的可执行bundle的基本配置信息

                ● 存储App的用户设置及配置信息

                ● 如:游戏类App经常会在Plist文件中存储游戏等级和分数信息

                ● App会将存储用户数据的Plist文件保存在“[App home目录]/documents/”目录下

                ● Plist文件可以是XML格式或二进制格式

                ● App可能使用Plist文件存储明文的用户名、密码或其它一些个人敏感信息

                ● 保存在Plist文件中的二进制格式文件数据则可以使用Plist文件编辑器(如plutil)进行查看或修改,即使在一个没有越狱的设备上,plist文件也可以通过工具iExplorer获取,对于以编码、未加密或弱加密形式存储的敏感信息就可能会导致敏感信息泄露

                ● 尽量不要在iOS设备的Plist文件中保存敏感信息(如证件号、银行卡号、详细住址及其各对应的编码格式等);

                ● 于有些APP功能需求,如果一定需要在iOS设备本地保存敏感信息,则可采用iOS提供的加密接口(如CommonCrypto)进行安全加密后保存。

        2、sqlite

                ● 一种自包含、可嵌入、0配置的SQL数据库引擎的跨平台C库文件

                ● 它的表、触发器和视图整个数据库都包含在一个硬盘文件中

                ● 一般会将其保存在“[App home目录]/documents/”目录下

                ● iOS自带的SQLite数据库没有内置的加密支持,因此,许多iOS APP会直接以明文格式将许多敏感数据        存储在SQLite数据库中,除非APP自身对数据进行加密后再存储

                ● SQLite仅会将该记录标记为已删除,但不会清除它们

                ● 只要SQLite数据库文件本身没被删除,数据库中被删除的记录则会一直保留在SQLite文件的未分配空间内,直到新的记录覆盖它们

                ● 最简单的方法就是尽量不在客户端的SQLite数据库中保存敏感信息

                ● 如果确实需要将某些敏感信息保存在SQLite数据库中时,可以结合使用以下几种方案:

                ● 数据加密:使用如AES256加密算法对数据进行安全加密后再存入SQLite中

                ● 整库加密:可使用第三方的SQLite扩展库,对数据库进行整体的加密

                ● 数据覆盖:在删除SQLite数据库某条记录之前,可以使用垃圾数据update一下该条目。这样即使有人尝试从SQLite文件中恢复已删除的数据库时,他们也无法获取到实际的数据

        3、 键盘缓存

                ● 为提供自动填充和纠正的功能,iOS系统的自带键盘会缓存用户的输入信息

                ● 其会保存一个接近600个单词的列表,存放在“Library/Keyboard/ en_GB-dynamic-text.dat”或“/private/var/mobile/Library/Keyboard/dynamic-text.dat”文件中

                ● 这个功能会带来一个安全问题:它会明文存储用户在输入框中输入过的所有信息,如用户名、密码短语、安全问题回答等

                ● 由于键盘会缓存这些输入框信息,使得在开始输入一个如安全问题答案的时候,缓存会帮助攻击者自动完成该问题的答案输入

                ●  首先,对于以下位置或方式的输入,iOS不会对其输入内容进行缓存: 

                ● 在标记为secure的字段、passwords字段内输入的内容不会缓存

                ● 输入只包括数字的字符串不会被缓存,这也即意味着银行卡号、信用卡号是安全的

                ● 非常短的输入,如只有1或者2个字母组成的单词不会被缓存

                ● 禁用了自动纠正功能的文本框会阻止输入内容被缓存

                ● 可以在不需要缓存的文本框处禁用自动纠正功能

                            UITextField *textField = [[UITextField alloc] initWithFrame: frame ];

                             textField.autocorrectionType = UITextAutocorrectionTypeNo;

                ● 输入框也可以被标记为密码输入类型,使得输入变得更加安全,防止缓存

                ● textField.secureTextEntry = YES;

                ● 在所有敏感信息输入处均使用自定义键盘,当然自定义键盘也不能缓存用户输入

                ● 另外除了文本输入的地方,在iOS系统上,当数据被复制到粘贴板上的时候,也会被进行明文缓存,而且粘贴板内容所有APP均可访问,为禁用文本框的复制/粘贴功能,使得用户无法在某些地方进行复制和粘贴

        4、 应用快照缓存

                ● 当一个应用在后台被挂起时,iOS会生成一个当前屏幕的快照,当应用被重新唤起时,可以快速还原该APP之前的内容,以提高用户的使用体验。

                ● 应用快照保存在“/var/mobile/Containers/Data/Application/XXXXXXX-XXXXXXXXX-XXXXXXXXX/Library/Caches/Snapshots/”目录下

                ● 屏幕内容就必须在iOS系统进行屏幕快照之前进行隐藏或模糊化处理,而iOS系统也提供了许多回调方法来提示程序将被挂起

                ● * (void)applicationWillResignActive:(UIApplication *)application ,应用程序将要入非活动状态执行,在此期间,应用程序不接收消息或事件 

                ● * (void)applicationDidEnterBackground:(UIApplication *)application ,程序将被推送到后台。

                ● 一个简单方法就是设置关键窗口的hidden属性为YES,这样当前在屏幕上显示的内容将被隐藏,返回一个空白的快照来替代任何内容。

                ● [UIApplication sharedApplication].keyWindow.hidden=YES;

                ● 果在当前窗口后面有其他的窗口,当关键窗口被隐藏时,那些窗口将会被显示出来。所以当使用这种方法时要确保也隐藏了其他窗口。

                ● 当应用程序即将进入非活动状态时(如接到一个电话或切换到其他应用程序时),applicationWillResignActive方法会被回调。因此可以用以下代码来隐藏窗口。

                         -(void)applicationWillResignActive:(UIApplication *)application  {

                                [UIApplication sharedApplication].keyWindow.hidden=YES;

                            }

                ● 另一个重要的地方是把这些代码加入到aplicationDidEnterBackground方法中,此方法会在APP被压入后台但在屏幕快照被调用前被调用。

                             -(void)applicationDidEnterBackground:(UIApplication *)application {

                                    [UIApplication sharedApplication].keyWindow.hidden=YES;

                             }

                ● 除隐藏当前界面内容外,还可以对当前界面所展示的内容进行模糊化处理。在上述的回调方法中,通过使用iOS的毛玻璃(blur glass)技术,可以达到程序后台运行界面的模糊化效果。

        5、应用日志

                ● 基于iOS APP程序开发排错的需要,开发人员一般都会写一些数据到日志中,而这些数据就可能包括证件号、登录用户名和密码、认证token或其它的一些敏感信息。

                ● 应用程序的错误日志是不被应用程序的沙盒隔离保护的,一个APP产生的错误日志可以被另一个APP读取。

                ● 在越狱iOS设备上,APP还可获取到其他应用输出所有的日志信息

                ● 不要在APP的日志中记录或打印敏感信息,并且在正式发布的时候,确保关闭了日志打印开关

        6、keychain存储

                ● Keychain是一个拥有有限访问权限的SQLite数据库(AES256加密)

                ● 可以为多种应用程序或网络服务存储少量的敏感数据(如用户名、密码、加密密钥等)

                ● 如保存身份和密码,以提供透明的认证,使得不必每次都提示用户登录。

                ● 在iPhone上,Keychain存放在“/private/var/Keychains/keychain-2.db”SQLite数据库

                ● Keychain数据库包含了一些Keychain条目,每个条目都由加密的数据和一系列未加密的描述属性组成,Keychain的条目类型(kSecClass)决定了其关联的一些描述属性,数字身份=证书+密钥

                ● 在iOS的Keychain中,所有的Keychain条目都被存储在Keychain SQLite数据库的4张表中:genp、inet、cert和keys

                ● genp数据表存储了普通密码的Keychain条目,inet数据表存储了网络密码的Keychain条目,cert和keys数据表分别存储了证书和密钥的Keychain条目

                ● Keychain的数据库内容使用了设备唯一的硬件密钥进行加密,该硬件密钥无法从设备上导出

                ● 存储在Keychain中的数据只能在该台设备上读取,而无法复制到另一台设备上解密后读取。

                ● iOS APP的Keychain数据是存储在应用沙箱外面的,各APP的keychain数据内容为逻辑隔离,由系统进程securityd实施访问控制

                ● 一个应用默认无法读取到另一个应用在Keychain中存储的数据

                ● 在iOS系统中,每个APP都附带一个唯一的应用标识符,而Keychain服务则使用这个应用标识符限制其对其它Keychain数据的访问。默认情况下,APP只能访问与他们的应用标识符相关联的数据

                ● 为了在多个APP间能够共享Keychain信息,Apple引入了Keychain访问组概念:拥有相同Keychain访问组标识符的应用,可以共享Keychain数据

                ● 随着iOS引入了数据保护机制,存储在Keychain中的数据被另一层与用户密码(passcode)相关联的加密机制保护着

                ● 数据保护加密密钥(保护类密钥-protection class keys)是由一个设备硬件密钥和一个由用户密码衍生的密钥共同产生的

                ● 可以通过向Keychain接口的SecItemAdd或SecItemUpdate方法的kSecAttrAccessible属性提供一个可访问常量来启用Keychain的数据保护

                ● 为避免每次提示用户登录,APP很可能会在Keychain中直接存储明文的认证信息

                ● APP在添加Keychain条目时可能也会设置数据保护的可访问常量,如前文所述,该可访问常量决定了Keychain条目何时才能被访问。而数据保护机制又是与用户密码相关联的,只有在当用户设置iOS密码时,它才会保护数据

                ● 一旦攻击者能够物理接触到没有设置密码的iOS设备时,他就可以通过越狱该设备,运行如keychain_dumper这样的工具,读取到设备所有的Keychain条目,获取里面存储的明文信息。而即使在应用向Keychain中存储数据时使用了数据保护的接口(即上文提到的keychain数据保护可访问常量),未设置用户密码的Keychain数据仍没有被有效地保护着

                ● 1, 尽量不在Keychain中直接存储明文的敏感信息。 

                ● 2, 向Keychain中存储数据时,不要使用kSecAttrAccessibleAlways,而是使用更安全的kSecAttrAccessibleWhenUnlocked或kSecAttrAccessibleWhenUnlockedThisDeviceOnly选项。 

                ● 3, 如果必须要存储,则可先检测用户是否设置了设备密码,并进行相应的风险提示。 

                ● 4, 对用户来说,想要保护Keychain中的数据,就是设置更强的密码,iOS默认允许4位数字口令(从0-9999),结合iOS的某些漏洞或设置,很容易被人快速暴力破解,而设置字母加数字的密码则会让破解过程花费更多的时间。

        7、NsUserDefault

                ●  iOS系统提供的一种保存信息和属性的非常普通的方法

                ● NSUserdefaults 的本质就是把数据存储在本地沙河目录的Library 目录下的Preferences 目录下bundleID. plist命名的文件中

                ● 当应用删除时,沙河目录下的数据一块跟着删除 ,对于应用中和应用安装相关的数据,可以存储在这里, 

        8、 coreData

        9、NSFileManager

你可能感兴趣的:(iOS本地数据存储)