IOS development NSURLSession/NSURLConnection HTTP load failed solution

Recently, I have been busy for the launch of the new storage app. I have been busy for nearly a month. After a period of 996, I can finally take a breath today and continue to update my blog. This paper records the problems and solutions encountered when sending a HTTPS request in iOS 9. It is hoped that through this paper, we can have a deeper understanding of the configuration of ATS.
Problem description
When developing app, I encountered the problem of sending HTTPS request in iOS 9 :

NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9801)

As we know, after , iOS 9, all network requests use HTTPS by default. If you send HTTP request, the following error will be reported. But we can allow HTTP request by setting the value of nsapptransportsecuritynsallowsarbitraryloads to be YES :

App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.


This solves the HTTP request problem, but when I send a HTTPS request, the HTTP laod failed problem still occurs. Although the above method can also be used to solve this problem, it is not the fundamental solution.
The solution
Through the analysis, doubt is TLS problem, because the 9 default need TLS1.2 iOS version to encrypt data, if the server does not support the TLS1.2 , the URLSession: task: didCompleteWithError: returns the nil error , However, the back-end development colleagues said that the server supports TLS1.0, TLS1.1 and TLS1.2, it seems that this is not the problem of TLS. Therefore, I was not assured. I used nscurl to test the test server. As expected, TLS1.2 was not supported.

# 加 --verbose 是为了显示详细的调试信息
/usr/bin/nscurl --ats-diagnostics --verbose

It can be seen from the output that the server only supports TLS1.0. Therefore, the colleagues in the background development were asked to test and modify, and then tested again. It was found that the server supports TLS1.2, and the network request of HTTPS is normal.

ATS exception configuration
In fact, for the server does not support TLS1.2, but the client to send HTTPS request there is another solution, is to configure ATS, set the lowest TLS version, as shown in infos.plist :


Where, the specific Settings of NSExceptionDomains are described below, where ATS can be understood in more detail
NSIncludesSubdomains: is applied to the domain name, the default is NONSExceptionAllowsInsecureHTTPLoads: whether to allow HTTP requests, YES (allow), the default is NONSExceptionMinimumTLSVersion: TLS version of the lowest NSExceptionRequiresForwardSecrecy: whether to pre encryption, NO (encryption is allowed, but does not support PFS: Perfect forward secrecy), default is YESNSRequiresCertificateTransparency: the need for effective signing certificate, YES (need), the default is NO

This paper just briefly introduces how to configure ATS, and solves the problem that HTTPS cannot be accessed because the server does not support TLS1.2. It is necessary to understand the specific workflow of HTTPS and TLS, please refer to relevant materials.
The resources
# # iOS issue record about NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, - 9801)
IOS 9 comes with a series of tutorials
IOS 9.0
Clean up the pits in iOS9 adaptation (graphic)
Cocoa Keys
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802) on a subdomain?

Read More: