我们正在尝试制作一个应用程序,该应用程序将使用NSURLSession通过HTTPS与我们的多个服务器进行通信,因为我们正在使用我们自己的根CA,该根CA捆绑在我们的应用程序中,并且ATS完全启用(NSAllowsArbitraryLoads设置为False)。
在调用NSURLSession Authentication委托(即“URLAuthenicationChallenge”)时,我们通过“SecTrustSetAnchorCertificates”设置锚证书,该证书通过验证其签名加上其证书链中的证书签名来验证证书,直到锚证书。还使用SecTrustSetAnchorCertificatesOnly排除其他锚点。
成功执行SecTrustEvaluate后,在SessionDataTask completionHandler中收到错误,如下所述:
[4704:1445043] ATS failed system trust
[4704:1445043] System Trust failed for [1:0x1c41678c0]
[4704:1445043] TIC SSL Trust Error [1:0x1c41678c0]: 3:0
[4704:1445043] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
(Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made."
注:
当设备上安装根CA证书并受信任时,启用ATS的HTTPS通信将正常工作,不会出现任何错误。但我不希望用户在设备上手动安装并信任根CA。
代码段:
func getRequest(){
let requestUrl = “https://server.test.com/hi.php” //url modified
let configuration = URLSessionConfiguration.default
var request = try! URLRequest(url: requestUrl, method: .get)
let session = URLSession(configuration: configuration,
delegate: self,
delegateQueue: OperationQueue.main)
let task = session.dataTask(with: request, completionHandler: { (data, response, error) in
print("Data = \(data)")
print("Response = \(response)")
print("Error = \(error)")
})
task.resume()
}
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping(URLSession.AuthChallengeDisposition, URLCredential?) -> Swift.Void){
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
let trust = challenge.protectionSpace.serverTrust
let rootCa = “root"
if let rootCaPath = NSBundle.mainBundle().pathForResource(rootCa, ofType: "der") {
if let rootCaData = NSData(contentsOfFile: rootCaPath) {
let rootCert = SecCertificateCreateWithData(nil, rootCaData).takeRetainedValue()
SecTrustSetAnchorCertificates(trust, [rootCert])
SecTrustSetAnchorCertificatesOnly(trust, true)
}
var trustResult: SecTrustResultType = 0
SecTrustEvaluate(trust, &trustResult)
if (Int(trustResult) == kSecTrustResultUnspecified ||
Int(trustResult) == kSecTrustResultProceed) {
// Trust certificate.
} else {
NSLog("Invalid server certificate.")
}
} else {
challenge.sender.cancelAuthenticationChallenge(challenge)
}
}
1条答案
按热度按时间f0brbegy1#
我认为实际的加密代码看起来是正确的,至少看起来是正确的,但是NSURLSession方面的事情并没有做正确的事情。
若干问题:
else
的例子中,你应该做的是:如果您不这样做,您将破坏诸如代理身份验证之类的功能,并且它可能在其他情况下也会破坏。
添加如下内容:
添加如下内容: