Swift 3 NSURLSession/NSURLConnection当连接到具有验证的站点时,HTTP加载失败

问题描述:

我以前见过这个错误,似乎补救措施是将信息添加到.plist文件。我已经试过每个我见过的那些的:Swift 3 NSURLSession/NSURLConnection当连接到具有验证的站点时,HTTP加载失败

How do I load an HTTP URL with App Transport Security enabled in iOS 9?

NSURLSession/NSURLConnection HTTP load failed on iOS 9

NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802) on a subdomain?

不过我的计划会导致同样的错误抛出:

2017- 05-08 08:29:37.781075-0400 xxxx [3256:408961] [] nw_coretls_callback_handshake_message_block_invoke_3 tls_handshake_continue:[-9812] 2017年5月8日08:29:37.781 XXXX [3256:408982] NSURLSession/NSURLConnection的HTTP加载失败(kCFStreamErrorDomainSSL,-9813)

我的相关代码是在这里:

let username = "xxxx" 
    let password = "xxxx" 
    let loginString = String(format: "%@:%@", username, password) 
    let loginData = loginString.data(using: String.Encoding.utf8)! 
    let base64LoginString = loginData.base64EncodedString() 

    let baseUrl = "https://xxxx" 
    var request = URLRequest(url: URL(string: baseUrl)! as URL) 

let baseUrl = "server i want.xml" 
     let request = NSMutableURLRequest(url: NSURL(string: baseUrl)! as URL) 
     request.httpMethod = "POST" 
     request.setValue("Basic \(base64LoginString)", forHTTPHeaderField: "Authorization") 
     let session = URLSession.shared 

     var err: NSError? 

     let task = session.dataTask(with: request as URLRequest) { 
      (data, response, error) in 

      if data == nil { 
       print("dataTaskWithRequest error: \(err)") 
       return 
      } 

      let xml = SWXMLHash.parse(data!) 
      let serialNumFromXML = xml["mobile_devices"]["mobile_device"]["serial_number"].element?.text 

func urlSession(
    _ session: URLSession, 
    didReceive challenge: URLAuthenticationChallenge, 
    completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) 
{ 
    completionHandler(
     .useCredential, 
     URLCredential(trust: challenge.protectionSpace.serverTrust!)) 
} 

我读过它可能与证书有关,但我不能更改服务器,因为我不负责它,所以我无法获得适当的证书。除了更换plist还有更多吗?

我的plist文件有允许任意加载和我的XML文件所在的域的例外域。

我可以得到测试文件的内容,如https://www.w3schools.com/xml/note.xml,但我需要的文件位于用户名/密码“Authentication Required”弹出框后面。

我也试过Alamofire库,会发生同样的事情:

nw_coretls_callback_handshake_message_block_invoke_3 tls_handshake_continue:[-9807] 2017年5月8日09:42:08.452 XXX [6128:888398] NSURLSession/NSURLConnection的HTTP加载失败(kCFStreamErrorDomainSSL,-9802)

+0

看到这一点:http://stackoverflow.com/a/43303169/3901620和http://stackoverflow.com/a/ 33227527/3901620 – KKRocks

+0

@KKRocks嗯。我只是做了自签名证书,但没有解决。 nscurl导致所有测试失败,但我不控制服务器,所以我无法修复它 – AON

好的好,我不知道如何解决这一问题,但我发现,Alamofire可以用来做什么,我需要。这是一个库存管理的本地项目,所以我不担心绕过证书的安全性。我的代码是在这里:

 Manager.delegate.sessionDidReceiveChallenge = { session, challenge in 
     var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling 
     var credential: URLCredential? 

     if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust, let trust = challenge.protectionSpace.serverTrust { 
      disposition = URLSession.AuthChallengeDisposition.useCredential 
      credential = URLCredential(trust: trust) 
     } else { 
      if challenge.previousFailureCount > 0 { 
       disposition = .cancelAuthenticationChallenge 
      } else { 
       credential = Manager.session.configuration.urlCredentialStorage?.defaultCredential(for: challenge.protectionSpace) 

       if credential != nil { 
        disposition = .useCredential 
       } 
      } 
     } 

     return (disposition, credential) 
    } 

private var Manager: Alamofire.SessionManager = { 

// Create the server trust policies 
let serverTrustPolicies: [String: ServerTrustPolicy] = [ 
    "https://SERVER:PORT": .disableEvaluation 
] 

// Create custom manager 
let configuration = URLSessionConfiguration.default 
configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders 
let manager = Alamofire.SessionManager(
    configuration: URLSessionConfiguration.default, 
    serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies) 
) 
let sessionManager = SessionManager(
    serverTrustPolicyManager: ServerTrustPolicyManager(
     policies: ["https://SERVER:PORT": .disableEvaluation] 
    ) 
) 
return manager 
}() 

open class MyServerTrustPolicyManager: ServerTrustPolicyManager { 

// Override this function in order to trust any self-signed https 
open override func serverTrustPolicy(forHost host: String) -> ServerTrustPolicy? { 
    return ServerTrustPolicy.disableEvaluation 
} 

}