如何使用 iOS 7 的 NSURLSession 接受自签名 SSL 证书

问题描述 投票:0回答:3

我有以下代码(快速实现):

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

func connection(connection: NSURLConnection, didReceiveAuthenticationChallenge challenge: NSURLAuthenticationChallenge)
{
    if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust
    {

        if challenge.protectionSpace.host == "myDomain"
        {
            let credentials = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust)
            challenge.sender.useCredential(credentials, forAuthenticationChallenge: challenge)
        }
    }

    challenge.sender.continueWithoutCredentialForAuthenticationChallenge(challenge)

}

它在 iOS 8.x 中完美运行,但在 iOS 7.x 中不起作用 在 iOS 7.x 中我遇到错误:

NSURLConnection/CFURLConnection HTTP 加载失败(kCFStreamErrorDomainSSL,-9813)

有什么想法吗? 谢谢你!!!

ios swift ssl https self-signed
3个回答
26
投票

无论如何,

connection:canAuthenticateAgainstProtectionSpace:
connection:didReceiveAuthenticationChallenge:
在iOS 8中均已弃用,因此您应该使用其他方法。

我在项目中使用的是 NSURLSessionDelegate 的委托方法。遵守该协议,然后添加此方法:

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

然后,当您使用初始化 NSURLSession 并将委托设置为 self 时。例如:

var session = NSURLSession(configuration: configuration, delegate: self, delegateQueue:NSOperationQueue.mainQueue())

然后使用该会话实例调用 dataTaskWithRequest 方法:

var task = session.dataTaskWithRequest(request){
    (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
    if error != nil {
        callback("", error.localizedDescription)
    } else {
        var result = NSString(data: data, encoding:
            NSASCIIStringEncoding)!
    }
}
task.resume()

可以在此处找到完整的工作示例。

出于安全原因,如果您使用自签名证书,我建议还实施公钥固定(https://gist.github.com/edwardmp/df8517aa9f1752e73353


0
投票

使用 URLSessionDelegate 继承类

创建会话对象

let config = URLSessionConfiguration.default


let session = Foundation.URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)


 let task = session.dataTask(with: httpRequest as URLRequest, completionHandler: {requestData, response, errorData -> Void in

            if errorData == nil {

                dataCallback(requestData! as NSData)
            }
            else {

                let error = NSError(domain: "Err-1001", code: 11, userInfo:nil)
                failureCallback(error)
            }
        });

        task.resume() 

添加委托方法

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

将其添加到您的 info.plist 文件中

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>xyc.com</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <true/>
            <key>NSExceptionMinimumTLSVersion</key>
            <string>TLSv1.2</string>
            <key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
            <false/>
            <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
            <true/>
            <key>NSThirdPartyExceptionMinimumTLSVersion</key>
            <string>TLSv1.2</string>
            <key>NSRequiresCertificateTransparency</key>
            <false/>
        </dict>
    </dict>
</dict>

-1
投票

Swift 5 解决方案

注意这些设置仅用于测试目的,请勿在生产应用程序中推送更改

步骤

  1. 在 info.plist 中的“应用程序传输安全设置”下将“允许任意加载”键添加为“YES”
  2. 创建新的会话对象并委托给 self
let config = URLSessionConfiguration.default  
let session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)
  1. 在当前类中实现 URLSessionDelegate 协议
extension YouClass: URLSessionDelegate {
    func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        completionHandler(URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
    }
}

修改版本: https://stackoverflow.com/a/30820452/3754976

© www.soinside.com 2019 - 2024. All rights reserved.