我们有一个react-native应用程序,它以这种方式使用react-native-keychain库(就像本期一样):
import * as Keychain from 'react-native-keychain';
try {
Keychain.setInternetCredentials(
'device-id',
'RANDOMDATA',
DeviceInfo.getUniqueID().toString(),
{ accessGroup: 'org.reactjs.native.example.myreactapp'})
.then(() => console.log('Done'))
} catch (err) {
console.log("error save", err)
}
我希望能够在我今天用 swift 制作的小部件中检索这些数据,我需要知道它的存储密钥。 以下是我应该将其恢复到小部件上的方法:
let itemKey = "device-id"
let keychainAccessGroupName = "3P********.org.reactjs.native.example.myreactapp"
let queryLoad: [String: AnyObject] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: itemKey as AnyObject,
kSecReturnData as String: kCFBooleanTrue,
kSecMatchLimit as String: kSecMatchLimitOne,
kSecAttrAccessGroup as String: keychainAccessGroupName as AnyObject
]
var result: AnyObject?
let resultCodeLoad = withUnsafeMutablePointer(to: &result) {
SecItemCopyMatching(queryLoad as CFDictionary, UnsafeMutablePointer($0))
}
if resultCodeLoad == noErr {
if let result = result as? Data,
let keyValue = NSString(data: result,
encoding: String.Encoding.utf8.rawValue) as String? {
// Found successfully
print("device-id : ", keyValue)
}
} else {
print("Error loading from Keychain: \(resultCodeLoad)")
}
以下代码来自此博客
但这不起作用。您可能已经注意到,我需要将设备 ID 传递给小部件,因为与 Android 不同,UUID 经常更改,并且我们在每个部分上获得不同的 ID,这会阻止小部件正常工作
在APP中更改此代码:
{ accessGroup: 'org.reactjs.native.example.myreactapp'})
到
{ accessGroup: '3P********.org.reactjs.native.example.myreactapp'})
这是我的解决方案:
在我的 React Native 应用程序中:
import * as Keychain from 'react-native-keychain';
export function saveToKeychain(key: AllowedKeychainKeysEnum, value: string) {
return Keychain.setInternetCredentials(
key,
key,
value,
{
accessible: Keychain.ACCESSIBLE.ALWAYS,
accessGroup: KEYCHAIN_GROUP,
},
);
}
使用这个函数可能看起来像这样:
saveToKeychain(ACCESS_TOKEN_NAME, accessToken)
现在在您的 swift 应用程序中:
func readFromKeychain(key: String) -> String? {
let query = [
kSecClass as String : kSecClassInternetPassword,
kSecAttrAccessGroup as String : keychainGroup,
kSecAttrServer as String : key,
kSecAttrAccount as String : key,
kSecReturnData as String : kCFBooleanTrue!,
kSecMatchLimit as String : kSecMatchLimitOne
] as [String : Any]
var dataTypeRef: AnyObject? = nil
let status: OSStatus = SecItemCopyMatching(query as CFDictionary, &dataTypeRef)
if status == noErr {
let text = String(data: dataTypeRef as! Data, encoding: String.Encoding.utf8)
return text
} else {
return nil
}
}
确保您创建了一个钥匙串组。本指南可以向您展示如何操作:https://evgenii.com/blog/sharing-keychain-in-ios/。
还要确保在代码中引用钥匙串组的任何地方都使用您的应用程序 ID 作为前缀。