使用Swift和NSURLSession固定的​​iOS证书

如何在Swift中将证书固定添加到NSURLSession?

OWASP website仅包含Objective-C和NSURLConnection的示例.

Swift 3更新:

只需为NSURLSessionDelegate定义一个委托类并实现didReceiveChallenge函数(此代码改编自objective-c Owasp示例):

class NSURLSessionPinningDelegate: NSObject,URLSessionDelegate {

    func urlSession(_ session: URLSession,didReceive challenge: URLAuthenticationChallenge,completionHandler: @escaping (URLSession.AuthChallengedisposition,URLCredential?) -> Swift.Void) {

        // Adapted from Owasp https://www.owasp.org/index.PHP/Certificate_and_Public_Key_Pinning#iOS

        if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
            if let serverTrust = challenge.protectionSpace.serverTrust {
                var secresult = SecTrustResultType.invalid
                let status = SecTrustEvaluate(serverTrust,&secresult)

                if(errSecSuccess == status) {
                    if let serverCertificate = SecTrustGetCertificateAtIndex(serverTrust,0) {
                        let serverCertificateData = SecCertificatecopyData(serverCertificate)
                        let data = CFDataGetBytePtr(serverCertificateData);
                        let size = CFDataGetLength(serverCertificateData);
                        let cert1 = NSData(bytes: data,length: size)
                        let file_der = Bundle.main.path(forResource: "certificateFile",ofType: "der")

                        if let file = file_der {
                            if let cert2 = NSData(contentsOfFile: file) {
                                if cert1.isEqual(to: cert2 as Data) {
                                    completionHandler(URLSession.AuthChallengedisposition.useCredential,URLCredential(trust:serverTrust))
                                    return
                                }
                            }
                        }
                    }
                }
            }
        }

        // Pinning Failed
        completionHandler(URLSession.AuthChallengedisposition.cancelAuthenticationChallenge,nil)
    }

}

(你可以找到一个Gist for Swift 2 here – from the initial answer)

然后使用openssl为您的网站创建.der文件

openssl s_client -connect my-https-website.com:443 -showcerts < /dev/null | openssl x509 -outform DER > my-https-website.der

并将其添加到xcode项目中.仔细检查它是否存在于“复制包资源”列表中的“构建阶段”选项卡中.否则将其拖放到此列表中.

最后在您的代码中使用它来发出URL请求:

if let url = NSURL(string: "https://my-https-website.com") {

    let session = URLSession(
            configuration: URLSessionConfiguration.ephemeral,delegate: NSURLSessionPinningDelegate(),delegateQueue: nil)


    let task = session.dataTask(with: url as URL,completionHandler: { (data,response,error) -> Void in
        if error != nil {
            print("error: \(error!.localizedDescription): \(error!)")
        } else if data != nil {
            if let str = Nsstring(data: data!,encoding: String.Encoding.utf8.rawValue) {
                print("Received data:\n\(str)")
            } else {
                print("Unable to convert data to text")
            }
        }
    })

    task.resume()
} else {
    print("Unable to create NSURL")
}

相关文章

软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘...
现实生活中,我们听到的声音都是时间连续的,我们称为这种信...
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿...
【Android App】实战项目之仿抖音的短视频分享App(附源码和...
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至...
因为我既对接过session、cookie,也对接过JWT,今年因为工作...