我有一个 iOS 项目。
我今天提取了一些身份验证代码并将其移至自己的项目中。
该项目支持 macOS 和 iOS。
我创建了一个包含 iOS 项目和 Auth 项目的工作区,并通过面板将身份验证添加.framework
到我的 iOS 项目中。Frameworks, Libraries, and Embedded Content
我可以构建和使用我的服务。我还设置了一个自定义方案CI_iOS
,允许我为这些项目运行测试。
我现在已经在我的 auth 模块中添加了一些集成测试,所以我可以KeychainTokenStore
针对真正的 Keychain 测试我的类。
这些在针对 macOS 测试我的模块时有效,但是尝试在 iOS 模拟器上运行它们都失败了。
我可以看到在尝试与钥匙串交互时返回错误代码-34018
,我相信这表明errSecMissingEntitlement
。
我一直在阅读一些似乎建议我需要启用钥匙串共享的帖子。
然而,我似乎无法完成这项工作。
我的KeychainTokenStore
长相是这样的
import Foundation
public protocol TokenStore {
typealias DeleteCacheResult = Result<Void, Error>
typealias DeleteCacheCompletion = (DeleteCacheResult) -> Void
typealias InsertCacheResult = Result<Void, Error>
typealias InsertCacheCompletion = (InsertCacheResult) -> Void
typealias RetrieveCacheResult = Result<String?, Error>
typealias RetrieveCacheCompletion = (RetrieveCacheResult) -> Void
/// The completion handler can be invoked in any thread.
/// Clients are responsible for dispatching to the appropriate thread, if needed.
func insert(_ token: String, key: String, completion: @escaping InsertCacheCompletion)
/// The completion handler can be invoked in any thread.
/// Clients are responsible for dispatching to the appropriate thread, if needed.
func delete(_ key: String, completion: @escaping DeleteCacheCompletion)
/// The completion handler can be invoked in any thread.
/// Clients are responsible for dispatching to the appropriate thread, if needed.
func retrieve(_ key: String, completion: @escaping RetrieveCacheCompletion)
}
public final class KeychainTokenStore: TokenStore {
public enum Error: Swift.Error {
case saveFailed
}
public init() { }
private lazy var queue = DispatchQueue(label: "KeychainTokenStore.queue", qos: .userInitiated, attributes: .concurrent)
public func insert(_ token: String, key: String, completion: @escaping InsertCacheCompletion) {
queue.async(flags: .barrier) {
completion(Result {
let query = [
kSecClass: kSecClassGenericPassword,
kSecAttrAccount: key,
kSecValueData: Data(token.utf8)
] as CFDictionary
SecItemDelete(query)
guard SecItemAdd(query, nil) == noErr else { throw Error.saveFailed }
})
}
}
public func delete(_ key: String, completion: @escaping DeleteCacheCompletion) {
queue.async(flags: .barrier) {
completion(Result {
let query = [
kSecClass: kSecClassGenericPassword,
kSecAttrAccount: key,
] as CFDictionary
SecItemDelete(query)
})
}
}
public func retrieve(_ key: String, completion: @escaping RetrieveCacheCompletion) {
queue.async {
let query = [
kSecClass: kSecClassGenericPassword,
kSecAttrAccount: key,
kSecReturnData: kCFBooleanTrue as Any,
kSecMatchLimit: kSecMatchLimitOne
] as CFDictionary
var result: AnyObject?
let status = SecItemCopyMatching(query, &result)
guard status == noErr, let data = result as? Data else {
return completion(.success(.none))
}
completion(Result {
String(decoding: data, as: UTF8.self)
})
}
}
}
在我的 iOS 应用程序中,我启用了如下共享:
当我尝试在我的身份验证框架中启用共享时,我看到以下内容
如何确保我的DigiAuth
框架可以通过运行我的DigiApp
项目来访问钥匙串?