ios - 为什么我不能在 swift 中使用客户端证书对 https 请求进行身份验证?
问题描述
- 我正在使用 XCode 12 编写一个 iOS 应用程序。
- 我正在使用本机 API(
URLSession
,URLSessionDelegate
等)。 - 我正在从 pfx12 blob 中读取SecIdentity 。
- 似乎没有任何问题
SecIdentity
。它加载没有错误,调试表明它不是零。 - 当我几乎一直在模拟器中运行我的应用程序时,就会发生这种情况。实际上,我之前已经用这个实现让它工作过,但是模拟器似乎进入了它开始发生的状态,然后我不能让它再次工作。
- 当我将 iPhone 连接到开发计算机并在其上运行它时,它就会执行此操作。
- 如果我用相同的客户端证书配置了失眠的 HTTPS 请求,它每次都有效。显然,我的应用程序发出请求的方式有所不同,但我不知道它是什么。
这是我的 URLSessionDelegate 实现。如您所见,它NSURLAuthenticationMethodClientCertificate
使用客户端证书身份创建的 URLCredential 响应:
fileprivate class SecureURLSessionDelegate: NSObject, URLSessionDelegate {
private let identity: SecIdentity
// nocov
init(withIdentity identity: SecIdentity) {
self.identity = identity
}
// maybecov
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate {
print("challenge identity: \(String(describing: self.identity))")
let credential = URLCredential(identity: self.identity,
certificates: nil,
persistence: .forSession)
print("responding with credential: \(credential.debugDescription)")
completionHandler(.useCredential, credential)
} else {
completionHandler(.performDefaultHandling, nil)
}
}
}
这是我对 URLSession 的初始化
extension URLSession {
convenience init(identity: SecIdentity, token: String) {
print("using identity: \(String(describing: identity))")
self.init(
configuration: URLSessionConfiguration.secured(withToken: token),
delegate: SecureURLSessionDelegate(withIdentity: identity),
delegateQueue: nil)
}
}
下面是不成功的 HTTPS 请求实现
private static func fetchAPIData(identity: SecIdentity, token: String, url: URL) -> AnyPublisher<Data, Error> {
let session = URLSession(identity: identity, token: token)
return session.dataTaskPublisher(for: url)
.handleEvents(
receiveCompletion: { _ in
session.finishTasksAndInvalidate()
},
receiveCancel: {
session.finishTasksAndInvalidate()
})
.eraseToAnyPublisher()
}
这是我从session.dataTaskPublisher()
电话中得到的结果
2021-07-30 14:44:56.936388-0700 SmoothBanking[41075:40401540] Task <1BAD4C76-7FA2-40D0-8A0B-93B5425C035C>.<1> finished with error [-1206] Error Domain=NSURLErrorDomain Code=-1206 "The server “api.teller.io” requires a client certificate." UserInfo={NSLocalizedDescription=The server “api.teller.io” requires a client certificate., NSErrorFailingURLStringKey=https://api.teller.io/accounts, NSErrorFailingURLKey=https://api.teller.io/accounts, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <1BAD4C76-7FA2-40D0-8A0B-93B5425C035C>.<1>"
), _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <1BAD4C76-7FA2-40D0-8A0B-93B5425C035C>.<1>, NSUnderlyingError=0x600003a51f80 {Error Domain=kCFErrorDomainCFNetwork Code=-1206 "(null)" UserInfo={NSErrorPeerAddressKey=<CFData 0x600001768370 [0x10d594b90]>{length = 16, capacity = 16, bytes = 0x100201bb2ce9e7b50000000000000000}}}}
我错过了什么?我什至验证了它正在运行委托,据我所知它正在提供凭证,但它只是不起作用。
解决方案
推荐阅读
- google-kubernetes-engine - 运行负载均衡器同步例程的 GKE 负载均衡器控制器出错:获取 Ingress 的机密时出错:机密“”不存在
- javascript - [TypeError:null 不是对象(评估 '_reactNativePdfLib.default.getDocumentsDirectory')]
- javascript - 如何查看批量发货单号?
- java - 三个属性相加后如何获得新列表
- python-decorators - 装饰器功能未按预期工作
- javascript - 导出/导入 useState 更改实用程序功能?
- c# - 实现评论列表删除以删除所有回复,如何?
- celery - 在 Celery 5.0 中删除了对这种用法的支持。相反,您应该使用 `-A` 作为全局选项: celery -A celeryapp worker <...>
- operating-system - 什么物理组件执行引导
- reactjs - 如何使用 React Native Expo 访问 cookie