首页 > 解决方案 > 为什么我不能在 swift 中使用客户端证书对 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}}}}

我错过了什么?我什至验证了它正在运行委托,据我所知它正在提供凭证,但它只是不起作用。

标签: iosswiftauthenticationhttpsclient-certificates

解决方案


推荐阅读