簡體   English   中英

使用鑰匙串在 iOS 擴展程序及其包含的應用程序之間共享?

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

我知道我可以通過啟用應用程序組和使用 NSUserDefaults 在我的共享擴展和它包含的應用之間共享數據(請參閱在 iOS 8 共享擴展和主應用之間共享數據)。

但是,我存儲的數據是敏感的,所以我希望使用鑰匙串。 因此,用戶將在包含的應用程序中輸入帳戶信息,然后共享擴展程序將讀取該數據以執行預期的共享操作。

有誰知道這是否可能? 我對它的第一次破解表明擴展程序和包含的應用程序具有單獨的鑰匙串(在嘗試返回擴展程序中該鍵的數據時,使用包含應用程序中的鍵保存數據返回 null)。

謝謝!

PS 使用 Lockbox 進行鑰匙串訪問,但如果它過於抽象而無法正常工作,我可以放棄它。 https://github.com/granoff/Lockbox

使鑰匙串在 Xcode 8 中共享。

1) 在 Capabilities 中的 App 目標中找到並打開“鑰匙串共享”,添加鑰匙串組密鑰(反向域樣式字符串,如 com.myappdomain.myappname)

2)對擴展目標執行完全相同的操作。 確保應用程序和擴展程序的鑰匙串組密鑰相同。

以您通常的方式從 Keychain 添加和檢索數據,無需對代碼進行特殊更改。 例如,以下是我將數據放入主應用程序中的 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)

然后在擴展中檢索它:

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

請注意,您仍需要將“登錄名”和“域”傳遞給擴展程序,以便識別正確的記錄。 這可以通過 NSUserDefaults 來完成。 請參閱有關如何執行此操作的答案

這是可以做到的。 它是創建一個框架來進行鑰匙串訪問,並在“功能”下打開“激活鑰匙串共享”的組合。 這個鏈接告訴我我需要知道的: http : //swiftandpainless.com/ios8-share-extension-with-a-shared-keychain/

使用標准的 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)

    }

在 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))

}

在 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”

我為應用程序和共享擴展的目標啟用了應用程序組功能。 然后我剛剛添加了屬性:

kSecAttrAccessGroup: "group.lolrandomname",

它工作正常:我可以從應用程序和我的共享擴展訪問相同的存儲項目:)

使用以下鏈接中的 KeychainItemWrapper 類並將您的組標識符作為訪問組傳遞。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM