Swift 3 NSURLSession/NSURLConnection HTTP load failed when connecting to a site with authentication

匿名 (未验证) 提交于 2019-12-03 02:38:01

问题:

I've seen this error around before and it seems the remedy is to add info to the .plist file. I've tried each of the ones I've seen:

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?

Still my program results in the same error thrown:

2017-05-08 08:29:37.781075-0400 xxxx[3256:408961] [] nw_coretls_callback_handshake_message_block_invoke_3 tls_handshake_continue: [-9812] 2017-05-08 08:29:37.781 xxxx[3256:408982] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)

My relevant code is here:

    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!)) }

I've read it may have to do with the certificate, but I can't change the server because I'm not in charge of it, so I can't get an appropriate certificate. Is there more to it than changing the plist?

My plist file had the Allow Arbitrary Loads and an exception domain for the domain that my XML file is on.

I can get the contents of a test file, like https://www.w3schools.com/xml/note.xml, but the file I need is behind a username/password "Authentication Required" popup.

I've also tried the Alamofire library, same thing occurs:

nw_coretls_callback_handshake_message_block_invoke_3 tls_handshake_continue: [-9807] 2017-05-08 09:42:08.452 xxx[6128:888398] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)

回答1:

Okay well I didn't know how to fix this but I discovered that Alamofire can be used to do what I needed. This is a local project for inventory management so I wasn't concerned about the security of bypassing the certificates. My code is here:

       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  }  }


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!