在 Swift 中使用具有有效 SSL 证书的 NSURLConnection

Using NSURLConnection with a valid SSL certificate in Swift

我对 IOS 开发比较陌生。所以请多多包涵,多多包涵!

我正在尝试使用 NSURLConnection 从 SOAP Web 服务取回数据,它工作正常。

但是,一旦我将 URL 从 http 更改为 https,我就不会再收到任何数据,也不会收到错误或任何我期望的错误。

https 证书是来自 godaddy 的有效证书,它设置正确,在所有浏览器上都能正确查看等等,所以基本上任何人都可以指出正确的方向,说明为什么从 http 更改为 https 时没有任何反应。 ....

代码在Swift中,如下:

    // Create the SOAP Message to send
    var soapMessage = "<?xml version='1.0' encoding='UTF-8'?><SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:ns1='http://tempuri.org/'><SOAP-ENV:Body><ns1:get_Test/></SOAP-ENV:Body></SOAP-ENV:Envelope>"

    NSLog("soapMessage generated is: %@", soapMessage)

    // Soap URL Works
    var urlString = "http://api.domain.com/testservice.svc"

    //Below https URL does not work
    //var urlString = "https://api.domain.com/testservice.svc"

    var url = NSURL(string: urlString)
    var theRequest = NSMutableURLRequest(URL: url!)

    //Get Length of request
    var msgLength = String(countElements(soapMessage))

    // POST Header values
    theRequest.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
    theRequest.addValue(msgLength, forHTTPHeaderField: "Content-Length")
    theRequest.addValue("http://tempuri.org/IService/get_Test", forHTTPHeaderField: "SoapAction")
    theRequest.HTTPMethod = "POST"
    theRequest.HTTPBody = soapMessage.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
    NSLog("Request is: %@", theRequest.allHTTPHeaderFields!)

    var connection = NSURLConnection(request: theRequest, delegate: self, startImmediately: true)
    connection?.start()

    if (connection == true) {
        var mutableData : Void = NSMutableData.initialize()
    }

进一步NSURL连接码为:

// NSURLConnectionDelegate
func connection(connection: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
    mutableData.length = 0;
}

func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {
    mutableData.appendData(data)
}


func connection(connection: NSURLConnection, didFailWithError error: NSError) {
    NSLog("Error with Soap call: %@", error)
}

func connectionDidFinishLoading(connection: NSURLConnection!) {
    var xmlParser = NSXMLParser(data: mutableData)
    xmlParser.delegate = self
    xmlParser.parse()
    xmlParser.shouldResolveExternalEntities = true
}
// NSURLConnectionDelegate

然后我有解析器的东西,比如 didStartElement、didEndElement、foundCharacters、parserDidEndDocument 等

我还添加了一些 NSURLConnection 的委托,如下所示,但没有任何改变。他们在日志显示时被调用。

 func connection(connection: NSURLConnection, canAuthenticateAgainstProtectionSpace protectionSpace: NSURLProtectionSpace?) -> Bool
{
     NSLog("am here")
    return protectionSpace?.authenticationMethod == NSURLAuthenticationMethodServerTrust
}

func connection(connection: NSURLConnection, didReceiveAuthenticationChallenge challenge: NSURLAuthenticationChallenge?)
{
     NSLog("am here 2")
    if challenge?.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust
    {
        if challenge?.protectionSpace.host == "api.domain.com"
        {
            NSLog("yep")
            let credentials = NSURLCredential(forTrust: challenge!.protectionSpace.serverTrust)
            challenge!.sender.useCredential(credentials, forAuthenticationChallenge: challenge!)
        }
    }
    challenge?.sender.continueWithoutCredentialForAuthenticationChallenge(challenge!)
}

它 运行s 通过代码到达 "yep" 所以据我所知应该信任证书,但是当我使用 https url 时仍然没有任何显示。

所以除了 https 之外的任何代码都没有区别,并且证书是正确有效的,那么我如何使用 https 而不是 http 取回数据?

非常感谢 - 如果这是一个愚蠢的问题,我们深表歉意!

戴夫

附加:

好的,我现在已将连接更改为:

    var connection = NSURLConnection(request: theRequest, delegate: self, startImmediately: false)
    connection?.start()

    if (connection == true) {
        var mutableData : Void = NSMutableData.initialize()
    } else {
        NSLog("Error with connection, details: %@", connection!)
    }

所以当我 运行 使用 SSL 时,这现在会记录 "Error with connection"!

然后我将 didreceiveresponse 更改为:

func connection(connection: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
    mutableData.length = 0;
    var httpresponse = response as? NSHTTPURLResponse
    println("status \(httpresponse?.statusCode)")
    println("headers \(httpresponse?.allHeaderFields)")
}

我看到返回的状态码是 404 - 我只是不明白,因为 Web 服务显然在那里,并且可以使用在线解析器进行解析!

所以仍然卡住了,但至少它指出了问题所在。有人有什么想法可以进一步帮助我吗?

如果其他人遇到困难,则 SVC 网络服务的网络配置已更改为:

     <bindings>
        <basicHttpBinding>
            <binding>
                <security mode="Transport">
                    <transport clientCredentialType="None"/>
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <services>
        <service name="Service.Service">
            <endpoint address="" binding="basicHttpBinding" contract="Service.IService" />
        </service>
    </services>

这修复了它,所以上面的 swift 代码现在可以正常工作了!哎呀,这是一个艰难的!