简体   繁体   English

使用钥匙串在 iOS 扩展程序及其包含的应用程序之间共享?

[英]Share between an iOS extension and its containing app with the keychain?

I understand I can share data between my share extension and its containing app by enabling app groups and using NSUserDefaults (see Sharing data between an iOS 8 share extension and main app ).我知道我可以通过启用应用程序组和使用 NSUserDefaults 在我的共享扩展和它包含的应用之间共享数据(请参阅在 iOS 8 共享扩展和主应用之间共享数据)。

However, the data I am storing is sensitive, so I hoped to use the keychain.但是,我存储的数据是敏感的,所以我希望使用钥匙串。 So the user would enter account information in the containing app, and then the share extension would read that data to perform the intended sharing action.因此,用户将在包含的应用程序中输入帐户信息,然后共享扩展程序将读取该数据以执行预期的共享操作。

Does anyone know if this is possible?有谁知道这是否可能? My first crack at it suggests that the extension and the containing app have separate keychains (saving the data with a key in the containing app returns null when attempting to return data for that key in the extension).我对它的第一次破解表明扩展程序和包含的应用程序具有单独的钥匙串(在尝试返回扩展程序中该键的数据时,使用包含应用程序中的键保存数据返回 null)。

Thanks!谢谢!

PS Using Lockbox for Keychain access, but I could ditch it if it's too much of an abstraction to make it work. PS 使用 Lockbox 进行钥匙串访问,但如果它过于抽象而无法正常工作,我可以放弃它。 https://github.com/granoff/Lockbox https://github.com/granoff/Lockbox

To make the Keychain shared in Xcode 8.使钥匙串在 Xcode 8 中共享。

1) In your App target in Capabilities find and turn on "Keychain Sharing", add a Keychain Group key (a reverse-domain style string like com.myappdomain.myappname) 1) 在 Capabilities 中的 App 目标中找到并打开“钥匙串共享”,添加钥匙串组密钥(反向域样式字符串,如 com.myappdomain.myappname)

2) Do exactly the same for the extension target. 2)对扩展目标执行完全相同的操作。 Make sure the Keychain Group key is the same for both - the app and the extension.确保应用程序和扩展程序的钥匙串组密钥相同。

Add and retrieve data from Keychain in your usual way, no special changes required in the code.以您通常的方式从 Keychain 添加和检索数据,无需对代码进行特殊更改。 For example, here's how I put data into Keychain in the main app (a little old-fashioned but still works in Swift 3):例如,以下是我将数据放入主应用程序中的 Keychain 的方法(有点老式,但在 Swift 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)

And then retrieve it in the extension:然后在扩展中检索它:

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(keychainQuery 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
    }
}

Note that you will still need to pass "login" and "domain" over to the extension in order to identify the correct record.请注意,您仍需要将“登录名”和“域”传递给扩展程序,以便识别正确的记录。 This can be done via NSUserDefaults.这可以通过 NSUserDefaults 来完成。 See this answer on how to do this.请参阅有关如何执行此操作的答案

This can be done.这是可以做到的。 It is a combination of creating a framework to do the Keychain access, and turning on "Activate Keychain Sharing" under "Capabilities".它是创建一个框架来进行钥匙串访问,并在“功能”下打开“激活钥匙串共享”的组合。 This link told me what I needed to know: http://swiftandpainless.com/ios8-share-extension-with-a-shared-keychain/这个链接告诉我我需要知道的: http : //swiftandpainless.com/ios8-share-extension-with-a-shared-keychain/

Using the standard Objective-C KeychainItemWrapper class and with an entry of #import "KeychainItemWrapper.h" in the bridging header:使用标准的 Objective-C KeychainItemWrapper 类并在桥接头中输入 #import "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)

    }

On the Watch extension side (Swift):在 Watch 扩展端 (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))

}

In Objective C, watchkit extension:在 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)]);

Don't forget to turn on "Keychain Sharing" under "Capabilities" for both the phone app and watch kit extension for same keychain group: "group.com.yourcompany.appid"不要忘记在“功能”下为同一钥匙串组的手机应用程序和手表套件扩展打开“钥匙串共享”:“group.com.yourcompany.appid”

I enabled the app groups functionality for both the app and the target of the Share Extension.我为应用程序和共享扩展的目标启用了应用程序组功能。 Then I just added the attribute :然后我刚刚添加了属性:

kSecAttrAccessGroup: "group.lolrandomname",

And it works correctly : I can access to same stored items from the App and from my Share Extension :)它工作正常:我可以从应用程序和我的共享扩展访问相同的存储项目:)

Use KeychainItemWrapper Class from the following link and pass your group identifier as accessgroup.使用以下链接中的 KeychainItemWrapper 类并将您的组标识符作为访问组传递。

https://developer.apple.com/library/ios/samplecode/GenericKeychain/Listings/Classes_KeychainItemWrapper_m.html https://developer.apple.com/library/ios/samplecode/GenericKeychain/Listings/Classes_KeychainItemWrapper_m.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在iOS App及其扩展程序之间共享情节提要 - Share Storyboard between iOS App and its Extension Appcelerator iOS 应用程序:如何从共享扩展中读取钥匙串值? - Appcelerator iOS app: how to read Keychain value from Share Extension? 如何在WatchKit扩展和iPhone应用程序之间共享钥匙串数据 - How to share keychain data between a WatchKit extension and an iPhone app 在iOS App和WatchKit Extension之间共享Plist - Share Plist between iOS App and WatchKit Extension 如何在主iOS应用与其共享扩展之间使用相同的经过身份验证的用户令牌 - How to use same Authenticated user token between main iOS app and its Share Extension 如何在iOS App包含扩展和扩展(不是主机应用程序)之间进行通信 - How to communicate between iOS App Containing Extension and Extension (not Host App) iOS使用Alamofire快速在应用程序和共享扩展之间共享Cookie - iOS swift using alamofire to share cookie between app and share extension 用于在共享扩展和iOS应用之间共享文件路径/文件的代码 - Code to share file path/file between a share extension and iOS app 共享扩展以打开包含应用程序 - Share Extension to open containing app 在iOS8中的App和App Extension之间共享用户对象 - Share User Object between App and App Extension in iOS8
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM