2016-11-07 152 views
10

我正在做一個URLSession,但該URL需要憑據。Swift 3 URLSession與URLCredential不起作用

我這裏這整個方法試圖做URLCredentials一個URLSession:

func loginUser(_ username: String, password: String, completion: @escaping (_ result: Bool) -> Void) 
    { 
     //Create request URL as String 

     let requestString = String(format:"%@", webservice) as String 

     //Covert URL request string to URL 

     guard let url = URL(string: requestString) else { 
      print("Error: cannot create URL") 
      return 
     } 

     //Convert URL to URLRequest 

     let urlRequest = URLRequest(url: url) 

     print(urlRequest) 

     //Add the username and password to URLCredential 

     credential = URLCredential(user:username, password:password, persistence: .forSession) 

     //Setup the URLSessionConfiguration 

     let config = URLSessionConfiguration.default 

     //Setup the URLSession 

     let session = URLSession(configuration: config, delegate: self, delegateQueue: nil) 

     //Prepare the task to get data. 

     let task = session.dataTask(with: urlRequest, completionHandler: { (data, response, error) in 

      DispatchQueue.main.async(execute: { 

       if(error == nil) 
       { 
        completion(true) 
       } 
       else 
       { 
        completion(false) 
       } 

      }) 

     }) 

     //Run the task to get data. 

     task.resume() 

    } 

,這裏是我的URLSessionDelegate方法:

func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { 

     if challenge.previousFailureCount > 0 
     { 
      completionHandler(Foundation.URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil) 
     } 
     else 
     { 
      completionHandler(Foundation.URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust:challenge.protectionSpace.serverTrust!)) 
     } 

    } 

    /** 
    Requests credentials from the delegate in response to an authentication request from the remote server. 
    */ 

    func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { 

     completionHandler(Foundation.URLSession.AuthChallengeDisposition.useCredential,credential) 

    } 

我注意到,當我在此代表調試這方法:

func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { 

     if challenge.previousFailureCount > 0 
     { 
      completionHandler(Foundation.URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil) 
     } 
     else 
     { 
      completionHandler(Foundation.URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust:challenge.protectionSpace.serverTrust!)) 
     } 

    } 

這個方法被調用兩次,當它h其此行的第二次:

completionHandler(Foundation.URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust:challenge.protectionSpace.serverTrust!)) 

我得到這個錯誤:

fatal error: unexpectedly found nil while unwrapping an Optional value 

,然後我的應用程序崩潰!我如何解決這個錯誤?

回答

0

由於challenge.protectionSpace.serverTrust在您嘗試強制拆包時零爲失效。

你應該解開serverTrust並處理它爲零。我的猜測是,當serverTrust是零challenge.error有一個值。

func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { 

    if challenge.previousFailureCount > 0 { 
     completionHandler(Foundation.URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil) 
    } else if let serverTrust = challenge.protectionSpace.serverTrust { 
     completionHandler(Foundation.URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: serverTrust)) 
    } else { 
     print("unknown state. error: \(challenge.error)") 
     // do something w/ completionHandler here 
    } 
} 
+0

委託方法的哪一部分的應用程序不會崩潰了,但是當我嘗試運行登錄方法不管是我輸入的(正確或錯誤的)信號,它直接進入這一行'print(「未知狀態。error:\(challenge.error)」)' – user979331

+0

調試完成後,它會轉到這行'completionHandler (Foundation.URLSession.AuthChallengeDisposition.useCredential,URLCredential(trust:serverTrust)) '但是然後以某種方式再次運行這個方法,然後轉到這一行:'print(「未知狀態。錯誤:\(challenge.error)「)' – user979331

+0

你確定在打印語句中沒有錯字?'(challenge.error)'應該被實際的錯誤對象 – Casey

0

這裏是語法每迅速3.

就首先驗證它進入

open func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Swift.Void){ 

    var disposition: URLSession.AuthChallengeDisposition = URLSession.AuthChallengeDisposition.performDefaultHandling 

    var credential:URLCredential? 

    if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust { 
     credential = URLCredential(trust: challenge.protectionSpace.serverTrust!) 

     if (credential != nil) { 
      disposition = URLSession.AuthChallengeDisposition.useCredential 
     } 
     else{ 
      disposition = URLSession.AuthChallengeDisposition.performDefaultHandling 
     } 
    } 
    else{ 
     disposition = URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge 
    } 

    if (completionHandler != nil) { 
     completionHandler(disposition, credential); 
    } 
} 
+0

取代。這裏有兩個問題。 。首先當我運行我的loginUser方法時,它運行兩次urlSession方法,第一次進入'disposition = URLSession.AuthChallengeDisposition.useCredential',然後第二次進入'disposition = URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge' – user979331

+0

也是這個如果(完成處理程序!= nil){'給我一個警告'比較類型的非可選值'(URLSession.AuthChallengeDisposition,URLCredential?) - > Void'nil總是返回true' – user979331

+0

您試圖打印' authenticationMethod' value for second。 –