在 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 代码现在可以正常工作了!哎呀,这是一个艰难的!
我对 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 代码现在可以正常工作了!哎呀,这是一个艰难的!