使用NSURLSession连接到具有无效证书的服务器(swift2,xcode7,ios9)

时间:2015-10-14 14:33:03

标签: xcode swift swift2 ios9 xcode7

我正在使用Xcode 7,Swift 2和iOS9。我想使用NSURLSession连接到Web服务,但是当我尝试连接时出现以下错误:

2015-10-13 16:07:33.595 XCTRunner[89220:4520715] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)
2015-10-13 16:07:33.604 XCTRunner[89220:4520571] Error with connection, details: Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “domainapi.com” which could put your confidential information at risk." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x7fac7b6facc0>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?,

这是我的代码:

func request( dataPost : String, successHandler: (response: String) -> Void)-> String {
        let destination:String =  "https://domainapi.com:8743/WebService/sendData"
        let request = NSMutableURLRequest(URL: NSURL(string: destination as String)!)
        request.HTTPMethod = "POST"
        let postString = dataPost
        request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
        request.setValue("0", forHTTPHeaderField: "Content-Length")
        request.setValue("application/xml", forHTTPHeaderField: "Content-Type")
        request.setValue("gzip,deflate", forHTTPHeaderField: "Accept-Encoding")
        request.setValue("Keep-Alive", forHTTPHeaderField: "Connection")
        NSLog("Body is: %@", request.HTTPBody!)
        NSLog("Request is: %@", request.allHTTPHeaderFields!)
        NSLog("URL is: %@", destination)

        let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
            data, response, error in


            if error != nil {
                NSLog("Error with connection, details: %@", error!)
                return
            }

            let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)

            successHandler(response: responseString as String!);
            NSLog("Data received: %@", data!)

        }

        task.resume()
        return "worked"
    }
    func viewDidLoad() {
        let dataPost : String = "<webservices>xml data sending</webservices>"
        request(dataPost, successHandler: {
            (response) in
            let text = response
            print(text)
        });

我已查看NSURLAuthenticationChallenge,但我似乎无法用我现有的代码来解决这个问题。所以我的问题是如何才能连接到服务器?我已经尝试将域名添加到Info.plist中的NSAppTransportSecurity,但这不起作用。打开NSAllowsArbitraryLoads也没有用。任何帮助将不胜感激。

6 个答案:

答案 0 :(得分:12)

请看一下这篇文章。Shipping an App With App Transport Security特别是有关自签名证书的部分。

您很可能需要表单的委托方法

func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
    completionHandler(
        .UseCredential, 
        NSURLCredential(trust: challenge.protectionSpace.serverTrust!)
    )
}

将此添加到我自己的使用NSURLSession的comms类中解决了这个问题。

答案 1 :(得分:5)

创建URL会话时,使用初始化程序,它将委托与配置一起设置,如下所示:

let urlSession = URLSession(configuration: urlSessionConfiguration, delegate: self, delegateQueue: nil)

然后,实现以下委托方法,它应该可以工作。

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

但是,请务必注意,这是一个安全问题,我们不应该尝试使用无效证书连接到服务器。

答案 2 :(得分:0)

打开您的info.plist作为源代码 添加以下内容:

    <key>NSAppTransportSecurity</key>
    <dict>
           <key>NSAllowsArbitraryLoads</key>
          <true/>
   </dict>

这应该有所帮助。

答案 3 :(得分:0)

我收到错误消息“此服务器的证书无效。您可能正在连接到冒充“ www.yoururl.com”的服务器,这可能会使您的机密信息受到威胁。”

我通过在httpclient文件中执行此操作来解决了这个问题。以下代码将完全忽略身份验证请求。

var session: URLSession?

session = URLSession(configuration: sessionConfiguration(), delegate: self, delegateQueue: nil)

private func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: (URLSession.AuthChallengeDisposition) -> Void) {
            completionHandler(
                .cancelAuthenticationChallenge
            )
        }

也不确定是否会影响上述内容,但是在我的info.plist中,我具有“允许传输安全设置”和子键值选项“允许任意加载”,我将其设置为“是”。

答案 4 :(得分:0)

很多答案都差不多了,但不完全。所以这是在 Xcode 12.4 上对我有用的内容

在我的请求类

    let session: URLSession
    let sessionDelegate: HTTPRequestDelegate
    private  init() {
        let configuration = URLSessionConfiguration.default
        // Some more configuration settings
        // ...

        sessionDelegate = HTTPRequestDelegate()
        session = URLSession(configuration: configuration,
                                 delegate:  sessionDelegate,
                                 delegateQueue: nil)
    }

地点:

public class HTTPRequestDelegate: NSObject, URLSessionDelegate
{
    // Get Challenged twice, 2nd time challenge.protectionSpace.serverTrust is nil, but works!
    public func urlSession(_ session: URLSession,
                    didReceive challenge: URLAuthenticationChallenge,
                    completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        print("In invalid certificate completion handler")
        if challenge.protectionSpace.serverTrust != nil {
            completionHandler(.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
        } else {
            completionHandler(.useCredential, nil)
        }
    }
}

答案 5 :(得分:-1)

对于SWIFT 4:

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