如何修复 iOS 中的“TIC SSL 信任错误”?
How to fix ‘TIC SSL Trust Error’ in iOS?
当我尝试使用网络服务登录应用程序时。
我也像下面这样设置我的 plist-file
我收到以下错误。
我的控制台上显示此错误
TIC SSL Trust Error [5:0x1c017fbc0]: 3:0
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
Task <E0C414FF-98C7-4E6B-876F-B9006465C8FD>.<1> HTTP load failed (error code: -1200 [3:-9802]
Apple 开发者文档指南。
ssl 更改 iOS 11 https://forums.developer.apple.com/thread/80197
证书查看器还有更具体的消息传递。在下面的屏幕截图中,您可以看到显示了针对特定信任错误的警告。在这种情况下,错误显示为“无法验证此证书(弱摘要算法)”,因为它是使用 SHA-1 签名的。
在某些情况下,连接到服务器并向其发出命令以进行测试很有用。对于典型的 Internet 协议(HTTP、SMTP、NNTP 等),您可以使用 telnet 工具执行此操作。但是,如果协议使用 TLS,这将不起作用。在这种情况下,您最好的选择是 openssl 工具的 s_client 子命令。清单 1 展示了如何使用该工具手动获取内容(记住 HTTPS 使用端口 443)。
清单 1 使用 openssl s_client
$ openssl s_client -connect www.apple.com:443
CONNECTED(00000003)
[...]
GET / HTTP/1.1
Host: www.apple.com
HTTP/1.1 200 OK
Server: Apache/2.2.3 (Oracle)
Content-Length: 9464
Content-Type: text/html; charset=UTF-8
ntCoent-Length: 9516
Cache-Control: max-age=47
Expires: Mon, 25 Jun 2012 16:18:24 GMT
Date: Mon, 25 Jun 2012 16:17:37 GMT
Connection: keep-alive
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
[...]
</html>
closed
$
s_client 子命令支持许多有用的调试选项。例如:
您可以提供 -cert 参数让它响应客户端证书请求。
您可以指定 -showcerts 选项以获取服务器提供的证书的完整列表。
-debug 和 -msg 选项启用低级调试功能。
有关这些选项等的更多信息,请参阅手册页。
以下代码适用于我。我为 NSURLSessionDelegate (didReceiveChallenge)
实现了委托方法
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:Nil];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
//Handle the response
}];
[task resume];
//NSURLSessionDelegate方法
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler{
if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]){
if([challenge.protectionSpace.host isEqualToString:@"yourdomain.com"]){
NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
}
}
}
您可以在 Appdelegate.m
中输入
代码如下:
@implementation NSURLRequest(DataController)
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString *)host{
return YES;
}
IKKA - 在Swift 4.2 版本
中的回答
extension CustomViewController: URLSessionDelegate {
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate) {
completionHandler(.rejectProtectionSpace, nil)
}
if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
completionHandler(.useCredential, credential)
}
}
}
Swift 5.1
您的 class 必须遵守 URLSessionDelegate 并实现 "didReceive Challenge" 功能。
这些 Apple 开发者页面说明了这个问题,并提供了很多关于如何安全解决这个问题的见解:
Handling an Authentication Challenge
Performing Manual Server Trust Authentication
以下示例说明了如何为开发或 QA 环境解决此问题:
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
#if DEBUG
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
if challenge.protectionSpace.host == "YourTrustedDevOrQaDomain" {
// At this point you can prevent a domain that is pretending to be a trusted domain by challenging the user to present some credentials or a security mechanism for authentication.
if let serverTrust = challenge.protectionSpace.serverTrust {
let credential = URLCredential(trust: serverTrust)
completionHandler(URLSession.AuthChallengeDisposition.useCredential, credential)
}
}
}
#endif
}
当我尝试使用网络服务登录应用程序时。
我也像下面这样设置我的 plist-file
我收到以下错误。 我的控制台上显示此错误
TIC SSL Trust Error [5:0x1c017fbc0]: 3:0
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
Task <E0C414FF-98C7-4E6B-876F-B9006465C8FD>.<1> HTTP load failed (error code: -1200 [3:-9802]
Apple 开发者文档指南。
ssl 更改 iOS 11 https://forums.developer.apple.com/thread/80197
证书查看器还有更具体的消息传递。在下面的屏幕截图中,您可以看到显示了针对特定信任错误的警告。在这种情况下,错误显示为“无法验证此证书(弱摘要算法)”,因为它是使用 SHA-1 签名的。
在某些情况下,连接到服务器并向其发出命令以进行测试很有用。对于典型的 Internet 协议(HTTP、SMTP、NNTP 等),您可以使用 telnet 工具执行此操作。但是,如果协议使用 TLS,这将不起作用。在这种情况下,您最好的选择是 openssl 工具的 s_client 子命令。清单 1 展示了如何使用该工具手动获取内容(记住 HTTPS 使用端口 443)。
清单 1 使用 openssl s_client
$ openssl s_client -connect www.apple.com:443
CONNECTED(00000003)
[...]
GET / HTTP/1.1
Host: www.apple.com
HTTP/1.1 200 OK
Server: Apache/2.2.3 (Oracle)
Content-Length: 9464
Content-Type: text/html; charset=UTF-8
ntCoent-Length: 9516
Cache-Control: max-age=47
Expires: Mon, 25 Jun 2012 16:18:24 GMT
Date: Mon, 25 Jun 2012 16:17:37 GMT
Connection: keep-alive
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
[...]
</html>
closed
$
s_client 子命令支持许多有用的调试选项。例如:
您可以提供 -cert 参数让它响应客户端证书请求。 您可以指定 -showcerts 选项以获取服务器提供的证书的完整列表。 -debug 和 -msg 选项启用低级调试功能。 有关这些选项等的更多信息,请参阅手册页。
以下代码适用于我。我为 NSURLSessionDelegate (didReceiveChallenge)
实现了委托方法NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:Nil];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
//Handle the response
}];
[task resume];
//NSURLSessionDelegate方法
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler{
if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]){
if([challenge.protectionSpace.host isEqualToString:@"yourdomain.com"]){
NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
}
}
}
您可以在 Appdelegate.m
中输入代码如下:
@implementation NSURLRequest(DataController)
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString *)host{
return YES;
}
IKKA - 在Swift 4.2 版本
中的回答extension CustomViewController: URLSessionDelegate {
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate) {
completionHandler(.rejectProtectionSpace, nil)
}
if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
completionHandler(.useCredential, credential)
}
}
}
Swift 5.1
您的 class 必须遵守 URLSessionDelegate 并实现 "didReceive Challenge" 功能。
这些 Apple 开发者页面说明了这个问题,并提供了很多关于如何安全解决这个问题的见解:
Handling an Authentication Challenge
Performing Manual Server Trust Authentication
以下示例说明了如何为开发或 QA 环境解决此问题:
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
#if DEBUG
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
if challenge.protectionSpace.host == "YourTrustedDevOrQaDomain" {
// At this point you can prevent a domain that is pretending to be a trusted domain by challenging the user to present some credentials or a security mechanism for authentication.
if let serverTrust = challenge.protectionSpace.serverTrust {
let credential = URLCredential(trust: serverTrust)
completionHandler(URLSession.AuthChallengeDisposition.useCredential, credential)
}
}
}
#endif
}