2017-03-21 24 views
1

最近のプロジェクトでは、Microsoft NTLM認証で保護されているSOAPとoData形式のサーバーからデータを取得しようとしましたが、オンラインの例のどれも実際には機能しませんでした。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) 
    } 
}