iOS 9.3:发生 SSL 错误,无法与服务器建立安全连接
iOS 9.3 : An SSL error has occurred and a secure connection to the server cannot be made
我在使用自签名证书时遇到以下错误
Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred
and a secure connection to the server cannot be made.
同时使用
为我的一个演示应用程序测试 Web 服务
- iOS 9.3
- XCode 7.3
- Swift 2.2
- Alamofire 3.3.0
- 和本地服务器:https://filename.hostname.net
注意: 在假设它重复之前,我会要求请一直阅读它,即使相同我已经向苹果开发论坛报告
使用 Alamofire 库
func testAlamofireGETRequest() -> Void
{
Alamofire.request(.GET, "https://filename.hostname.net/HelloWeb/service/greeting/john")
.responseJSON
{ response in
print("Response JSON: \(response.result.value)")
}
}
使用NSURLSession
func testNSURLSessionRequest() -> Void {
let session = NSURLSession.sharedSession()
let urlString = "https://filename.hostname.net/HelloWeb/service/greeting/john"
let url = NSURL(string: urlString)
let request = NSURLRequest(URL: url!)
let dataTask = session.dataTaskWithRequest(request) { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
print("done, error: \(error)")
//Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made.
}
dataTask.resume()
}
I spent 2 days with no luck :(
there are bunch of questions already posted but nothing worked for me
- How to handle “CFNetwork SSLHandshake failed” in iOS
发布了 Alamofire git 问题
- 'CFNetwork SSLHandshake failed (-9847)' error when performing a non-SSL request #538
- Self-Signed Certificate not accepted #876
- how can I connecting my server as HTTPS with using self-signed Certificate file #977
我的 Info.pist 文件以这种方式更新了 ATS 设置
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>filename.hostname.net</key>
<dict>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
与此同时,我能够收到
的回复
http://filename.hostname.net
和https://google.com
但不适用于https://filename.hostname.net
任何人都可以告诉我为什么我付出了巨大的努力还是无法让它工作吗?
Apple 已发布应用程序传输安全的完整要求列表。
原来我们使用的是 TLS v1.2,但缺少一些其他要求。
- TLS 至少需要 1.2 版。
- 连接密码仅限于提供前向保密的密码(请参阅下面的密码列表。)
- 该服务要求证书至少使用 SHA256 指纹和 2048 位或更大的 RSA 密钥,或者 256 位或更大的椭圆曲线 (ECC) 密钥。
- 无效的证书会导致硬故障和无连接。
- 接受的密码是:
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
在 OS X 中的命令行,运行 以下内容:
nscurl --ats-diagnostics https://filename.hostname.net --verbose
这将告诉您哪些 ATS 设置组合允许和不允许 iOS 访问您的站点,并且应该指出您的站点存在什么问题。
可能是以下一项或多项
- 证书哈希算法(必须是 SHA-256 或以上)
- TLS 版本(必须是 1.2)
- TLS 算法(必须提供完美前向保密)
我假设您尝试连接的服务器的证书无效或不符合 iOS 9 ECC、密码等标准。
如果您使用的是高级网络 API——NSURLSession、NSURLConnection 或任何在这些之上的层级——您无法直接控制所提供的密码套件由客户。那些 API 使用他们自己的内部逻辑选择一组密码套件。
如果您使用的是较低级别的网络 APIs—CFSocketStream,通过它的 NSStream 和 CFStream APIs,以及任何比这更低的网络—您可以明确选择您要使用的一组密码套件。你如何做到这一点取决于具体的 API.
标准做法是:
创建流对
为 TLS 配置它
使用 kCFStreamPropertySSLContext 获取安全传输上下文 属性
在该上下文中配置特定属性
打开流
您可以在 TLSTool 示例代码中看到这方面的示例。具体来说,看看 TLSToolServer class,在那里你可以准确地看到这个序列。
在非常短的上下文中,您希望以绕过安全性的方式配置流,但是,对于 Alamofire,您可以直接通过以下方式执行此操作:
func bypassAuthentication() {
let manager = Alamofire.Manager.sharedInstance
manager.delegate.sessionDidReceiveChallenge = { session, challenge in
var disposition: NSURLSessionAuthChallengeDisposition = .PerformDefaultHandling
var credential: NSURLCredential?
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
disposition = NSURLSessionAuthChallengeDisposition.UseCredential
credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!)
} else {
if challenge.previousFailureCount > 0 {
disposition = .CancelAuthenticationChallenge
} else {
credential = manager.session.configuration.URLCredentialStorage?.defaultCredentialForProtectionSpace(challenge.protectionSpace)
if credential != nil {
disposition = .UseCredential
}
}
}
return (disposition, credential)
}
}
如果有帮助请告诉我。
谢谢!
我遇到了同样的情况,卡住了一天。尝试使用您的移动数据,如果这对您的 API 没有问题,那么您的网络防火墙有问题。然后从防火墙设置中启用 SSL/TLS。
我在使用自签名证书时遇到以下错误
Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made.
同时使用
为我的一个演示应用程序测试 Web 服务- iOS 9.3
- XCode 7.3
- Swift 2.2
- Alamofire 3.3.0
- 和本地服务器:https://filename.hostname.net
注意: 在假设它重复之前,我会要求请一直阅读它,即使相同我已经向苹果开发论坛报告
使用 Alamofire 库
func testAlamofireGETRequest() -> Void
{
Alamofire.request(.GET, "https://filename.hostname.net/HelloWeb/service/greeting/john")
.responseJSON
{ response in
print("Response JSON: \(response.result.value)")
}
}
使用NSURLSession
func testNSURLSessionRequest() -> Void {
let session = NSURLSession.sharedSession()
let urlString = "https://filename.hostname.net/HelloWeb/service/greeting/john"
let url = NSURL(string: urlString)
let request = NSURLRequest(URL: url!)
let dataTask = session.dataTaskWithRequest(request) { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
print("done, error: \(error)")
//Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made.
}
dataTask.resume()
}
I spent 2 days with no luck :(
there are bunch of questions already posted but nothing worked for me
- How to handle “CFNetwork SSLHandshake failed” in iOS
发布了 Alamofire git 问题
- 'CFNetwork SSLHandshake failed (-9847)' error when performing a non-SSL request #538
- Self-Signed Certificate not accepted #876
- how can I connecting my server as HTTPS with using self-signed Certificate file #977
我的 Info.pist 文件以这种方式更新了 ATS 设置
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>filename.hostname.net</key>
<dict>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
与此同时,我能够收到
的回复http://filename.hostname.net
和https://google.com
但不适用于https://filename.hostname.net
任何人都可以告诉我为什么我付出了巨大的努力还是无法让它工作吗?
Apple 已发布应用程序传输安全的完整要求列表。
原来我们使用的是 TLS v1.2,但缺少一些其他要求。
- TLS 至少需要 1.2 版。
- 连接密码仅限于提供前向保密的密码(请参阅下面的密码列表。)
- 该服务要求证书至少使用 SHA256 指纹和 2048 位或更大的 RSA 密钥,或者 256 位或更大的椭圆曲线 (ECC) 密钥。
- 无效的证书会导致硬故障和无连接。
- 接受的密码是:
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
在 OS X 中的命令行,运行 以下内容:
nscurl --ats-diagnostics https://filename.hostname.net --verbose
这将告诉您哪些 ATS 设置组合允许和不允许 iOS 访问您的站点,并且应该指出您的站点存在什么问题。
可能是以下一项或多项
- 证书哈希算法(必须是 SHA-256 或以上)
- TLS 版本(必须是 1.2)
- TLS 算法(必须提供完美前向保密)
我假设您尝试连接的服务器的证书无效或不符合 iOS 9 ECC、密码等标准。
如果您使用的是高级网络 API——NSURLSession、NSURLConnection 或任何在这些之上的层级——您无法直接控制所提供的密码套件由客户。那些 API 使用他们自己的内部逻辑选择一组密码套件。
如果您使用的是较低级别的网络 APIs—CFSocketStream,通过它的 NSStream 和 CFStream APIs,以及任何比这更低的网络—您可以明确选择您要使用的一组密码套件。你如何做到这一点取决于具体的 API.
标准做法是:
创建流对
为 TLS 配置它
使用 kCFStreamPropertySSLContext 获取安全传输上下文 属性
在该上下文中配置特定属性
打开流
您可以在 TLSTool 示例代码中看到这方面的示例。具体来说,看看 TLSToolServer class,在那里你可以准确地看到这个序列。
在非常短的上下文中,您希望以绕过安全性的方式配置流,但是,对于 Alamofire,您可以直接通过以下方式执行此操作:
func bypassAuthentication() {
let manager = Alamofire.Manager.sharedInstance
manager.delegate.sessionDidReceiveChallenge = { session, challenge in
var disposition: NSURLSessionAuthChallengeDisposition = .PerformDefaultHandling
var credential: NSURLCredential?
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
disposition = NSURLSessionAuthChallengeDisposition.UseCredential
credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!)
} else {
if challenge.previousFailureCount > 0 {
disposition = .CancelAuthenticationChallenge
} else {
credential = manager.session.configuration.URLCredentialStorage?.defaultCredentialForProtectionSpace(challenge.protectionSpace)
if credential != nil {
disposition = .UseCredential
}
}
}
return (disposition, credential)
}
}
如果有帮助请告诉我。 谢谢!
我遇到了同样的情况,卡住了一天。尝试使用您的移动数据,如果这对您的 API 没有问题,那么您的网络防火墙有问题。然后从防火墙设置中启用 SSL/TLS。