Swift 3 NSURLSession/NSURLConnection 使用身份验证连接到站点时 HTTP 加载失败

Swift 3 NSURLSession/NSURLConnection HTTP load failed when connecting to a site with authentication

我以前见过这个错误,似乎补救措施是将信息添加到 .plist 文件。我已经尝试了我见过的每一个:

我的程序仍然导致抛出相同的错误:

2017-05-08 08:29:37.781075-0400 xxxx[3256:408961] [] nw_coretls_callback_handshake_message_block_invoke_3 tls_handshake_continue: [-9812] 2017-05-08 08:29:37.781 xxxx[3256:408982] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)

我的相关代码在这里:

    let username = "xxxx"
    let password = "xxxx"
    let loginString = String(format: "%@:%@", username, password)
    let loginData = loginString.data(using: String.Encoding.utf8)!
    let base64LoginString = loginData.base64EncodedString()

    let baseUrl = "https://xxxx"
    var request = URLRequest(url: URL(string: baseUrl)! as URL)

let baseUrl = "server i want.xml"
        let request = NSMutableURLRequest(url: NSURL(string: baseUrl)! as URL)
        request.httpMethod = "POST"
        request.setValue("Basic \(base64LoginString)", forHTTPHeaderField: "Authorization")
        let session = URLSession.shared

        var err: NSError?

        let task = session.dataTask(with: request as URLRequest) {
            (data, response, error) in

            if data == nil {
                print("dataTaskWithRequest error: \(err)")
                return
            }

            let xml = SWXMLHash.parse(data!)
            let serialNumFromXML = xml["mobile_devices"]["mobile_device"]["serial_number"].element?.text

func urlSession(
    _ session: URLSession,
    didReceive challenge: URLAuthenticationChallenge,
    completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
{
    completionHandler(
        .useCredential,
        URLCredential(trust: challenge.protectionSpace.serverTrust!))
}

我看过可能跟证书有关,但是我不能换服务器,因为我不负责,所以我拿不到合适的证书。除了更改 plist 之外,还有更多吗?

我的 plist 文件具有允许任意加载和我的 XML 文件所在域的异常域。

我可以获取测试文件的内容,例如 https://www.w3schools.com/xml/note.xml,但我需要的文件在 username/password "Authentication Required" 弹出窗口后面。

我也试过 Alamofire 库,同样的事情发生了:

nw_coretls_callback_handshake_message_block_invoke_3 tls_handshake_continue: [-9807] 2017-05-08 09:42:08.452 xxx[6128:888398] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)

好吧,我不知道如何解决这个问题,但我发现 Alamofire 可以用来做我需要的事情。这是一个用于库存管理的本地项目,因此我并不担心绕过证书的安全性。我的代码在这里:

       Manager.delegate.sessionDidReceiveChallenge = { session, challenge in
        var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling
        var credential: URLCredential?

        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust, let trust = challenge.protectionSpace.serverTrust {
            disposition = URLSession.AuthChallengeDisposition.useCredential
            credential = URLCredential(trust: trust)
        } else {
            if challenge.previousFailureCount > 0 {
                disposition = .cancelAuthenticationChallenge
            } else {
                credential = Manager.session.configuration.urlCredentialStorage?.defaultCredential(for: challenge.protectionSpace)

                if credential != nil {
                    disposition = .useCredential
                }
            }
        }

        return (disposition, credential)
    }

private var Manager: Alamofire.SessionManager = {

// Create the server trust policies
let serverTrustPolicies: [String: ServerTrustPolicy] = [
    "https://SERVER:PORT": .disableEvaluation
]

// Create custom manager
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders
let manager = Alamofire.SessionManager(
    configuration: URLSessionConfiguration.default,
    serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
let sessionManager = SessionManager(
    serverTrustPolicyManager: ServerTrustPolicyManager(
        policies: ["https://SERVER:PORT": .disableEvaluation]
    )
)
return manager
}()

open class MyServerTrustPolicyManager: ServerTrustPolicyManager {

// Override this function in order to trust any self-signed https
open override func serverTrustPolicy(forHost host: String) -> ServerTrustPolicy? {
    return ServerTrustPolicy.disableEvaluation
 }

}