2016-10-22 2 views
2

Я делаю почтовый вызов на сервер, и я все время получал ошибку, что сертификат сервера был недействительным, поэтому после исследования я обнаружил, что должен доверять серверу с помощью проверки подлинности. Это проходит отлично (я печатаю запрос проверки подлинности, чтобы убедиться, что он это делает), но остальная часть вызова не проходит, и я не могу получить информацию с моего сервера, после проверки подлинности ничего не происходит, обычно я ожидаю будут возвращены данные. Однако ничего не происходит, и ни одно из моих urlsessiondatadelegates не называется (проверено с перерывами).URL-адреса делегатов, которые не вызываются после вызова аутентификации

Может ли кто-нибудь определить, почему это может быть? Код:

var request = URLRequest(url: URL(string: "https://45.56.105.97:7915/search-v2")!) 
request.httpMethod = "POST" 
request.addValue("Basic ***********", forHTTPHeaderField: "Authorization") 

let task = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue.main) 
      task.dataTask(with: request) { (data, response, error) in 
       print(error) 
       print(data) 
       if let responseData = NSString(data: data!, encoding: String.Encoding.utf8.rawValue){ 
            print("data: \(responseData)") 
            self.parseXML(data!) 

           } 
     }.resume() 

метода делегат:

func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { 
    print("did autherntcationchallenge = \(challenge.protectionSpace.authenticationMethod)") 

    if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust { 
     print("send credential Server Trust") 
     let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!) 
     challenge.sender!.use(credential, for: challenge) 

    }else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic{ 
     print("send credential HTTP Basic") 
     let defaultCredentials: URLCredential = URLCredential(user: "username", password: "password", persistence:URLCredential.Persistence.forSession) 
     challenge.sender!.use(defaultCredentials, for: challenge) 

    }else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodNTLM{ 
     print("send credential NTLM") 

    } else{ 
     challenge.sender!.performDefaultHandling!(for: challenge) 
    } 

} 
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) { 
    print("Data received: \(data)") 
} 

func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) { 

    print("Response received: \(response)") 
} 

func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { 
    print("something went wrong: \(error)") 
} 

func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) { 
    print("rep: \(response)") 
} 

После запуска, все я получаю отпечатанный:

сделал autherntcationchallenge = NSURLAuthenticationMethodServerTrust отправить CREDENTIAL доверенный SERVER

Я также видел беседы о том, как я могу использовать только методы закрытия или делегирования для извлечения данных/не оба. Я пробовал все без успеха.

** Также я знаю, что я не должен просто слепо доверять серверу, но я пытаюсь выяснить, почему я не могу получить данные обратно, я знаю, что это имеет серьезные недостатки безопасности.

+1

Когда эти методы делегата предоставить обработчик завершения, вы должны вызвать этот обработчик завершения, иначе соединение не будет продолжаться. – Rob

+0

Вызывается ли «urlsessiondatadelegates» или нет, если вы звоните, пожалуйста, поделитесь своим кодом? –

ответ

3

Есть две проблемы:

  • Как Rob уже упоминалось в комментариях, вы не называя обработчики завершения в любой из ваших методов делегата. Это означает, что соединение перестанет достигать прогресса в этой точке.
  • Вы вызываете методы отправителя вызова для предоставления учетных данных. Это будет работать с NSURLConnection, но NSURLSession требует, чтобы вы сделали это, вызвав обработчик завершения. В противном случае все будет очень сильно нарушаться, IIRC, например.

    completionHandler(.PerformDefaultHandling, nil) 
    
+0

Я попробовал то, что вы предложили, он действительно вызывает обработчик завершения, но я столкнулся с ошибкой: Сертификат для этого сервера недействителен. Возможно, вы подключаетесь к серверу, который притворяется _________________. Это была та же ошибка, которая побудила меня включить метод делегирования проверки подлинности. –

+0

Это потому, что сертификат сервера недействителен. Способ решения этой проблемы заключается в проверке сертификата другим способом (например, путем проверки того, является ли его открытый ключ тем, который вы ожидаете, или путем изменения защитного пространства, чтобы разрешить другой сертификат root/anchor, а затем проверить действительность сертификата снова), и если он передает эту проверку, вместо выполнения обработки по умолчанию, вы говорите ей использовать предоставленный сертификат. В любом случае, вы делаете это, вызывая обработчик завершения, потому что вызов методов в отправителе вызовов не будет делать ничего в любом случае. :-) – dgatwood

+1

Я рекомендую прочитать это: https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/OverridingSSLChainValidationCorrectly.html для получения дополнительной информации о том, как написать такой метод. Это все Obj-C, последний раз я проверил, но, по крайней мере, дает вам представление о различных подходах, которые вы можете использовать для безопасного использования. – dgatwood

Смежные вопросы