iOS Keychain(钥匙串) 原理和APP之间共享信息(例如:账号密码)
2016-12-02 00:00
435 查看
Keychain 介绍
英文好的点这官方文档Keychain Services 是 macOS 和 iOS 都提供一种安全地存储敏感信息的工具,比如,网络密码:用于保存访问服务器或者网站,通用密码:用来保存应用程序或者数据库密码.与此同时,用于认证的证书,密钥,和身份信息,也可以存储在Keychain中.Keychain Services 的安全机制保证了存储这些敏感信息不会被窃取。简单说来,Keychain 就是一个安全容器。
PS:在iOS中keychian 依赖用于签名的provisioning profile描述文件,确保发布不同版本的时候使用同一个pp文件
Keychain 的结构
Keychain 可以包含任意数量的 keychain item。每一个 keychain item 包含数据和一组属性。对于一个需要保护的 keychain item,比如密码或者私钥(用于加密或者解密的string字节)数据是加密的,会被 keychain 保护起来的;对于无需保护的 keychain item,例如,证书,数据未被加密。跟keychain item有关系的取决于item的类型;应用程序中最常用的是网络密码(Internet passwrods)和普通的密码。正如你所想的,网络密码像安全域(security domain)、协议、和路径等一些属性。在macOS中,当keychain被锁的时候加密的item没办法访问,如果你想要该问被锁的item,就会弹出一个对话框,需要你输入对应keychain的密码。当然,未有密码的keychain你可以随时访问。但在iOS中,你只可以访问你自已的keychain items;
Keychain的特点
数据并不存放在App的Sanbox中,即使删除了App,资料依然保存在keychain中。如果重新安装了app,还可以从keychain获取数据。keychain的数据可以用过group方式,让程序可以在App间共享。不过得要相同TeamID
keychain的数据是经过加密的
##Keychain的使用
大多数iOS应用需要用到Keychain, 都用来添加一个密码,修改一个已存在Keychain item或者取回密码。Keychain提供了以下的操作
SecItemAdd 添加一个item
SecItemUpdate 更新已存在的item
SecItemCopyMatching 搜索一个已存在的item
SecItemDelete 删除一个keychain item
####读取
func readPassword() throws -> String { /* 查找 对应 service, account and access group 的keychainItem. */ var query = KeychainPasswordItem.keychainQuery(withService: service, account: account, accessGroup: accessGroup) query[kSecMatchLimit as String] = kSecMatchLimitOne query[kSecReturnAttributes as String] = kCFBooleanTrue query[kSecReturnData as String] = kCFBooleanTrue // 查找已经存在的item var queryResult: AnyObject? let status = withUnsafeMutablePointer(to: &queryResult) { SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0)) } // 检查插入或更新是否成功 guard status != errSecItemNotFound else { throw KeychainError.noPassword } guard status == noErr else { throw KeychainError.unhandledError(status: status) } // 读取item中的密码信息 guard let existingItem = queryResult as? [String : AnyObject], let passwordData = existingItem[kSecValueData as String] as? Data, let password = String(data: passwordData, encoding: String.Encoding.utf8) else { throw KeychainError.unexpectedPasswordData } return password }
####写入
func savePassword(_ password: String) throws { // 编码Encoding->data let encodedPassword = password.data(using: String.Encoding.utf8)! do { // 查找是否存在item. try _ = readPassword() // 如果存在更新item中的密码 var attributesToUpdate = [String : AnyObject]() attributesToUpdate[kSecValueData as String] = encodedPassword as AnyObject? let query = KeychainPasswordItem.keychainQuery(withService: service, account: account, accessGroup: accessGroup) let status = SecItemUpdate(query as CFDictionary, attributesToUpdate as CFDictionary) guard status == noErr else { throw KeychainError.unhandledError(status: status) } } catch KeychainError.noPassword { /* 如果不存在 创建一个dictionary 作为item 存入keychain */ var newItem = KeychainPasswordItem.keychainQuery(withService: service, account: account, accessGroup: accessGroup) newItem[kSecValueData as String] = encodedPassword as AnyObject? let status = SecItemAdd(newItem as CFDictionary, nil) guard status == noErr else { throw KeychainError.unhandledError(status: status) } } }
##关于共享
Keychain的数据可以透过Group Access的方式,让资料可以在App间共享,Google系列的App (Gmail、Google+、日历…)就是通过这样的方式来记录使用者登入信息,只要使用者在其中一个App中完成登入了,其他的App也可以读取到同相的登入咨询进行登录。
###进入Capabilities,将Keychain打开
开启Keychain后,会自动新增一个Keychain Group,使用的是Bundle Identifier。
同时也会自动新增一个entitlements文件,里面也会有一个Access Group,名为
$(AppIdentifierPrefix)+你的bundleID
(AppIdentifierPrefix)可以是开发者的代号需要登录才会有,也就是开发者证书后小括号的内的英文数字组合。使用$(AppIdentifierPrefix)只能被同一个开发者账号的app来存取,以防被有心人盜取。
若其他的App也要存取当前Keychain的数据,就必需在Keychain开启后,新增相同的Keychain Group (Access Group会根据Keychain Group自动新增)。
PS: 需要Info.plist新增一对键值
Key: AppIdentifierPrefix
Value: $(AppIdentifierPrefix)
方便取得 Identifier Prefix
##最终效果
官方sampleCode
相关文章推荐
- iOS 用keychain钥匙串保存账号、设备UUID及APP间共享
- IOS在钥匙串里保存APP的账号密码
- iOS app之间共享数据的几种方法
- iOS: 在iPhone和Apple Watch之间共享数据: App Groups
- iOS开发之App间账号共享与SDK封装
- 在同一个进程的AppDomain之间共享信息
- iOS如何将APP的信息保存到沙盒之外(钥匙串中)
- 关于 账号密码等隐私信息的存储-------KeychainItemWrapper和SFHFKeychainUtils
- Facebook iOS SDK 3.5.1版本 优化app和社交网络之间的信息分享
- IOS 用keychain(钥匙串)保存用户名和密码
- iOS开发之App间账号共享与SDK封装
- iOS app之间共享数据的几种方法
- 75.iOS使用KeyChain存储数据与不同App间共享数据
- IOS中使用sskeychain调用keychain(钥匙串)保存密码
- iOS app之间共享数据的几种方法
- iOS: 在iPhone和Apple Watch之间共享数据: App Groups
- IOS 用keychain(钥匙串)保存用户名和密码
- iOS Keychain钥匙串,应用间数据共享打造iOS上的全家桶
- 钥匙串 keyChain 存储账号密码
- iOS Keychain钥匙串,应用间数据共享打造iOS上的全家桶