zoukankan      html  css  js  c++  java
  • 使用URLSession 连接https

    环境:
    macOS Monterey 12.0.1、
    Xcode 13.1、
    Swift 5.5.1

    1. 网络的基础请求
      涉及类: URL, URLRequest, URLSession, URLResponse
            let url = URL(string: "https://local.lexandera.com/openapi/login.json")
            let request = URLRequest(url: url!, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 30)
            let session = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
            session.dataTask(with: request) { data, response, error in
                if let data = data {
                    print(String(data: data, encoding: .utf8) as Any)
                }
                
                print(response as Any)
                if let e = error {
                    print(e.localizedDescription)
                }
            }.resume()
    

    此处是使用了block的形式获取了数据, 同时也可以选择代理的方式获取更详细的请求过程

            session.dataTask(with: request).resume()
    .....
    .....
    
        func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
            print(#function)
        }
        
        func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
            print(#function)
            guard let response = task.response as? HTTPURLResponse else { return }
            print(response.allHeaderFields)
        }
    
    1. 验证证书
      实现URLSessionDelegate的验证证书的代理方法
    func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
    
    }
    

    AFNetworking验证https证书的方式有3种,

    • 无条件认可
      使用服务端给过来的证书重新给回代理即可
       let ser = challenge.protectionSpace.serverTrust
       let m = URLCredential(trust: ser!)
       completionHandler(.useCredential, m)
    
    • 验证证书
            let ser = challenge.protectionSpace.serverTrust
            let path = Bundle.main.path(forResource: "server", ofType: "cer")
            if let cer = SecTrustGetCertificateAtIndex(ser!, 0) {
                let n = SecCertificateCopyData(cer) as Data
                print(n)
                do {
                    let data = try Data(contentsOf: .init(fileURLWithPath: path!))
                    let cer2 = SecCertificateCreateWithData(nil, data as CFData)
                    if cer == cer2 {
                        print("本地证书是一样的")
                        let credential = URLCredential(trust: ser!)
                        challenge.sender?.use(credential, for: challenge)
                        completionHandler(.useCredential, credential)
                        return
                    }
                } catch {
                    print("本地并没有该证书")
                }
            }
            completionHandler(.cancelAuthenticationChallenge, nil)
    
    • 验证公钥
       let publicKey  = SecCertificateCopyKey(cer)
       let publicKey2 = SecCertificateCopyKey(cer2)
    

    当我们使用Finder, Charles这类代理工具抓包的时候, 它们会把一个他们自己的自签名证书给到我们,这个时候我们比对证书的时候 就知道证书有问题了, 拒绝/取消请求即可

           completionHandler(.rejectProtectionSpace, nil)     
           completionHandler(.cancelAuthenticationChallenge, nil)      
    
    

    注: 关于自签名证书的获取

    1. 该文将会告诉你怎么获取crt证书 然后使用以下命令导出cer
    $ openssl x509 -in demo.crt -out demo.cer -outform der
    
    1. 将crt文件双击导入到钥匙串(KeyChain)中,然后右键导出为cer文件即可

    2. 访问拥有自签名证书的网站,在提醒安全页面,信任并访问它.然后在查看钥匙串,你将发现那个证书已经在钥匙串中,之后右键导出为cer文件即可.

    番外: 使用Combine请求数据

    func testNetwork2() {
        let cancellable = URLSession.shared.dataTaskPublisher(for: URL(string: "https://local.lexandera.com/openapi/login.json")!)
    //            .map{ data , _ in data}
            .subscribe(on: RunLoop.main)
    //            .print()
            .sink { completion in
            switch completion {
            case .finished:
                break
            case .failure(_):
                return
            }
            print("hahah")
        } receiveValue: { data in
            print(data)
        }
    }
    
  • 相关阅读:
    提取数据用strpos函数比较,预期和实际不符问题解决
    thinkphp模板中foreach循环没数据的错误解决
    错误之thinkphp模型使用发生的错误
    ThinkPHP添加模板时,犯的三个错
    mysql中的comment用法
    在cmd下输入/g无效
    Windows下PHPUnit安装
    python中string.casefold和string.lower区别
    python3数据类型
    python终端颜色设置
  • 原文地址:https://www.cnblogs.com/gulong/p/15753207.html
Copyright © 2011-2022 走看看