我之前尝试过所有以前的答案,但没有一个对我有用。我可能知道问题所在,我猜这个错误是误导性的。 我正在尝试向 https 但没有 SSL 的服务器发出 api 请求。此外,api 只能通过 VPN 工作。所以我禁用了 SSL 验证,它在任何地方(在模拟器、postman、android、mac 中)都可以正常工作,除了真正的 iOS 设备。
到目前为止我得到的线索是:
- DNS 污染 - 我在许多设备上尝试了很多次,但都无法正常工作。如果是 DNS,它在其他 Android 和 Mac 上是如何工作的。
- VPN 隧道 - 我看到了 VPN 软件的发布日志,这个确切的错误是一个错误,但现在已修复。我仍在使用他们的应用程序,我在 iPhone 上使用 VPN 尝试了我的 Mac 互联网仍然是同样的错误。
从字面上看,错误似乎是我的代码或一些逻辑上需要在 iOS 上完成才能在真实设备上实际工作以确保安全(如果存在的话)。
所以在这里我将分享到目前为止在模拟器上运行的实现(在此之前我在模拟器上遇到了同样的错误)。
我在我的路由器类中实现了 URLSessionDelegate,并允许在 info.plist 中进行任意加载。所以都是好的 url、请求等。
代理没有在真实设备上被调用。
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
completionHandler(.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
}
在提出请求之前:
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config, delegate: self, delegateQueue: .main)
信息 plist 文件内容
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>*my.domain*.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
</dict>
</dict>
</dict>
控制台错误:
[] nw_proxy_resolver_create_parsed_array PAC evaluation error:
NSURLErrorDomain: -1003
2018-06-26 20:12:08.646042+0530 MyApp[806:161960] TIC TCP Conn Failed [1:0x1c416f000]: 12:8 Err(-65554)
2018-06-26 20:12:08.646740+0530 MyApp[806:161964] Task <DCE45907-5758-4CC0-91A1-9EFD53FFDA0A>.<1> HTTP load failed (error code: -1003 [12:8])
2018-06-26 20:12:08.646971+0530 MyApp[806:161964] Task <DCE45907-5758-4CC0-91A1-9EFD53FFDA0A>.<1> finished with error - code: -1003
Error Domain=NSURLErrorDomain Code=-1003 "A server with the specified hostname could not be found." UserInfo={NSUnderlyingError=0x1c044cfc0 {Error Domain=kCFErrorDomainCFNetwork Code=-1003 "(null)" UserInfo={_kCFStreamErrorCodeKey=8, _kCFStreamErrorDomainKey=12}}, NSErrorFailingURLStringKey=https://my.domain.com/myurl/public/api, NSErrorFailingURLKey=https://my.domain.com/myurl/public/api, _kCFStreamErrorDomainKey=12, _kCFStreamErrorCodeKey=8, NSLocalizedDescription=A server with the specified hostname could not be found.}
2018-06-26 20:14:17.727091+0530 MyApp[806:161970] Received XPC error Connection interrupted for message type 3 kCFNetworkAgentXPCMessageTypePACQuery
2018-06-26 20:14:17.727533+0530 MyApp[806:161970] Received XPC error Connection invalid for message type 3 kCFNetworkAgentXPCMessageTypePACQuery
最佳答案
通过替换检查
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
completionHandler(.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
}
跟随
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
if challenge.protectionSpace.authenticationMethod == (NSURLAuthenticationMethodServerTrust) {
let serverTrust:SecTrust = challenge.protectionSpace.serverTrust!
var localCertificateTrust = SSLCertificateCreateTrustResult(serverTrust)
SecTrustEvaluate(serverTrust, &localCertificateTrust)
if true
{
let credential:URLCredential = URLCredential(trust: serverTrust)
challenge.sender?.use(credential, for: challenge)
completionHandler(URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
} else {
completionHandler(URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil)
}
}
else
{
completionHandler(URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil);
}
}
fileprivate func SSLCertificateCreateTrustResult(_ serverTrust: SecTrust)->SecTrustResultType {
let certificate: SecCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0)!
let remoteCertificateData = CFBridgingRetain(SecCertificateCopyData(certificate))!
let cerPath: String = Bundle.main.path(forResource: "cert", ofType: "der")!
let localCertificateData = NSData(contentsOfFile:cerPath)!
print(localCertificateData.length)
print((remoteCertificateData as! NSData).length)
let certDataRef = localCertificateData as CFData
let cert = (SecCertificateCreateWithData(nil, certDataRef))
let certArrayRef = [cert] as CFArray
SecTrustSetAnchorCertificates(serverTrust, certArrayRef)
SecTrustSetAnchorCertificatesOnly(serverTrust, false)
let trustResult: SecTrustResultType = SecTrustResultType.invalid
return trustResult
}
在我的案例中,这里还有整个运输安全。
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>dev-domainserver/portal</key>
<dict>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.2</string>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
关于iOS 错误代码=-1003 “A server with the specified hostname could not be found.”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51004899/