在iOS扩展之间共享,并且它包含带钥匙串的应用程序?
我知道我可以通过启用应用程序组和使用NSUserDefaults在我的共享扩展和其包含的应用程序之间共享数据(请参阅Sharing data between an iOS 8 share extension and main app)。在iOS扩展之间共享,并且它包含带钥匙串的应用程序?
但是,我存储的数据是敏感的,所以我希望使用钥匙串。因此,用户将在包含应用程序中输入帐户信息,然后共享扩展将读取该数据以执行预期的共享操作。
有谁知道这是可能的吗?我对它的第一个破解表明,扩展和包含的应用程序具有单独的钥匙串(在试图返回扩展中的该密钥的数据时,用包含应用程序中的键保存数据返回null)。
谢谢!
P.S.使用Lockbox进行Keychain访问,但如果它太抽象以使其工作,我可以抛弃它。 https://github.com/granoff/Lockbox
这可以做到。它是创建一个框架来完成钥匙串访问,并打开“功能”下的“激活钥匙串共享”的组合。此链接告诉我我需要知道的内容:http://swiftandpainless.com/ios8-share-extension-with-a-shared-keychain/
使用标准的Objective-C KeychainItemWrapper类和与所述桥接报头的#进口的条目 “KeychainItemWrapper.h”:
func btnSaveAction() {
let appGroupID = "group.com.yourcompany.appid"
let keychain = KeychainItemWrapper(identifier: "Password", accessGroup:appGroupID)
keychain.setObject(self.txtfldPassword.text!, forKey:kSecValueData)
keychain.setObject(self.txtfldEmail.text!, forKey:kSecAttrAccount)
}
在观看伸展侧(SWIFT):
override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)
let appGroupID = "group.com.yourcompany.appid"
let keychain = KeychainItemWrapper(identifier: "Password", accessGroup:appGroupID)
println(keychain.objectForKey(kSecAttrAccount))
println(keychain.objectForKey(kSecValueData))
}
在Objective C,watchkit延伸:
NSString *appGroupID = @"group.com.yourcompany.appid";
KeychainItemWrapper *keychain = [[KeychainItemWrapper alloc] initWithIdentifier:@"Password" accessGroup:appGroupID];
[keychain setObject:(__bridge id)(kSecAttrAccessibleWhenUnlocked) forKey:(__bridge id)(kSecAttrAccessible)];
NSLog(@"account = %@", [keychain objectForKey:(__bridge id)(kSecAttrAccount)]);
NSLog(@"password =%@", [keychain objectForKey:(__bridge id)(kSecValueData)]);
不要忘了打开“钥匙扣共享”,“功能”下同时为手机应用程序,并注意同组钥匙扣套件扩展:“group.com.yourcompany.appid”
为了使钥匙扣在Xcode 8.
1)共享在你的应用目标在功能找到并打开“钥匙扣共享”,添加一个钥匙串组密钥(反向域风格串等com.myappdomain.myappname)
2 )对扩展目标完全相同。确保钥匙串组密钥对于应用和扩展都是相同的。
以通常的方式添加和检索Keychain中的数据,代码中无需进行特殊更改。例如,这里是我如何把数据放到钥匙串在主应用程序(有点老套,但是在斯威夫特3仍然有效):
let login = loginString
let domain = domainString
let passwordData: Data = passwordString.data(using: String.Encoding.utf8, allowLossyConversion: false)!
let keychainQuery: [NSString: NSObject] = [
kSecClass: kSecClassGenericPassword,
kSecAttrAccount: login as NSObject, // login and domain strings help identify
kSecAttrService: domain as NSObject, // the required record in the Keychain
kSecValueData: passwordData as NSObject]
SecItemDelete(keychainQuery as CFDictionary) //Deletes the item just in case it already exists
let keychainSaveStatus: OSStatus = SecItemAdd(keychainQuery as CFDictionary, nil)
然后在扩展检索:
let keychainQuery: [NSString: NSObject] = [
kSecClass: kSecClassGenericPassword,
kSecAttrAccount: login as NSObject,
kSecAttrService: domain as NSObject,
kSecReturnData: kCFBooleanTrue,
kSecMatchLimit: kSecMatchLimitOne]
var rawResult: AnyObject?
let keychain_get_status: OSStatus = SecItemCopyMatching(keychainQueryForPass as CFDictionary, &rawResult)
if (keychain_get_status == errSecSuccess) {
if let retrievedData = rawResult as? Data,
let password = String(data: retrievedData, encoding: String.Encoding.utf8) {
// "password" contains the password string now
}
}
请注意,您仍然需要将“登录”和“域”传递给扩展,以便识别正确的记录。这可以通过NSUserDefaults完成。有关如何操作,请参阅this answer。
这是非常有用的不链接到其他网站或至少添加相关的来源的答案,该链接不再可用。 – leolobato 2015-07-29 14:30:14
这里有相当多的信息,我不喜欢蒸馏和粘贴,但这里是Internet Archive版本:https://web.archive.org/web/20141028160328/http://dasdev.de/2014/ 08/12/ios8-share-extension-with-a-shared-keychain – 2015-07-30 15:12:22
GitHub repo仍然存在https://github.com/dasdom/KeychainDemo太 – 2015-10-22 09:55:30