2017-03-21 235 views
1

對於最近的一個項目,我嘗試從SOAP和oData格式的服務器分別獲取一些數據,這些數據受Microsoft NTLM身份驗證保護,並且它一直是一個噩夢,想知道如何去做,沒有一個在線例子真的有效。Swift 3 NTLM身份驗證

回答

5

所以這裏是我的解決方案;我不得不適應,擴大和結合幾個不同的來源。我希望這可以幫助未來的人。

// 
// ViewController.swift 
// ntlm 
// 
// Created by Kamik423 on 21.3.17. 
// Copyright © 2017 Kamik423 All rights reserved. 
// 
// You might have to allow arbitrary loads!! 
// 
// Adapted from: 
//  https://gist.github.com/stevenschobert/f374c999e5cba6ccf09653b846967c83 
//  https://blogs.msdn.microsoft.com/chiranth/2013/09/20/ntlm-want-to-know-how-it-works/ 

import UIKit 

class ViewController: UIViewController { 

    var username: String? = nil 
    var password: String? = nil 

    lazy var conn: URLSession = { 
     let config = URLSessionConfiguration.ephemeral 
     let session = URLSession(configuration: config, delegate: self, delegateQueue: nil) 
     return session 
    }() 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     username = "<username>" 
     password = "<password>" 
     ntlm() 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 

    func ntlm() { 
     let urlString = "<url>" 
     let url = URL(string: urlString) 
     let request = NSMutableURLRequest(url: url!, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 60000) 
     request.httpMethod = "GET" 
     let task = conn.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in 
      print(response) 
      print(error) 
      print(String(data: data!, encoding: .utf8)) 
     }) 
     task.resume() 
    } 

    func doesHaveCredentials() -> Bool { 
     guard let _ = self.username else { return false } 
     guard let _ = self.password else { return false } 
     return true 
    } 
} 

extension ViewController: URLSessionDelegate { 

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

     print("got challenge") 

     guard challenge.previousFailureCount == 0 else { 
      print("too many failures") 
      challenge.sender?.cancel(challenge) 
      completionHandler(.cancelAuthenticationChallenge, nil) 
      return 
     } 

     guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodNTLM else { 
      print("unknown authentication method \(challenge.protectionSpace.authenticationMethod)") 
      challenge.sender?.cancel(challenge) 
      completionHandler(.cancelAuthenticationChallenge, nil) 
      return 
     } 

     guard self.doesHaveCredentials() else { 
      challenge.sender?.cancel(challenge) 
      completionHandler(.cancelAuthenticationChallenge, nil) 
      DispatchQueue.main.async { 
       print("Userdata not set") 
      }; 
      return 
     } 

     let credentials = URLCredential(user: self.username!, password: self.password!, persistence: .forSession) 
     challenge.sender?.use(credentials, for: challenge) 
     completionHandler(.useCredential, credentials) 
    } 
}