2016-11-07 107 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。 –