我正在开发一个使用HTTPS连接到服务的测试应用程序。此连接的证书使用自定义根证书。所以我为`NSURLSessionDelegate'实现了委托。并像这样实现:
func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
let trust: SecTrustRef = challenge.protectionSpace.serverTrust!
var secresult: SecTrustResultType = SecTrustResultType(kSecTrustResultInvalid)
if SecTrustEvaluate(trust, &secresult) == errSecSuccess {
switch (Int(secresult)) {
case kSecTrustResultUnspecified:
break
case kSecTrustResultProceed:
let credential = NSURLCredential(forTrust: trust)
completionHandler(.UseCredential, credential)
return
default:
print("default")
}
}
}
completionHandler(.CancelAuthenticationChallenge, nil)
}
我进入案例kSecTrustResultProceed
,但此处显示的代码导致无限循环。我总是遇到这个错误:
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
我怀疑这是因为用户不信任证书,所以我读了SFCertificateTrustPanel
用户可以接受证书信任的地方。然而,这种方法似乎无法从Swift获得。
如何在swift中使用SFCertificateTrustPanel
?
我是否有另一种方式可以信任证书,例如基于指纹?
答案 0 :(得分:1)
我不知道你有什么理由不能使用Swift中的 SFCertificateTrustPanel ,假设你使用的是OS X.话虽如此,你做不了多少你不能做的事情在应用程序内。
您需要做的是修改保护空间以允许您的特定TLS证书。我建议阅读Apple的文章“Overriding TLS Chain Validation Correctly”。您需要将TLS证书加载到NSData对象中,将其转换为SecCertificateRef,然后将其添加到SecTrustRef对象。大多数(但不是全部)步骤都包含在上面链接的文档中。
如果您要在不同的服务器上使用不同的证书,处理这种情况的正确方法是在看到新证书时使连接失败,然后显示一个对话框,询问用户是否信任该证书(例如给它指纹)。如果用户说“是”,则将该证书导出到NSData对象(例如,以DER形式)并将其存储在NSUserDefaults中的可信证书数组中,并将该证书数组中的每个项目添加到您的自定义中的信任对象中信任评估功能。
最后要注意的是:各种TLS库的iOS版本都有一堆额外的方法,可以更容易地从磁盘上的文件IIRC读取密钥和证书,并且更容易在NSData表示和实际证书或RSA密钥之间进行转换。尽管文档中提到了这些方法,但这些方法都可以在OS X上使用,因为它们是iOS模拟器运行所必需的。 : - )