使用URLSession 连接https
环境:
macOS Monterey 12.0.1、
Xcode 13.1、
Swift 5.5.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)
}
- 验证证书
实现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)
注: 关于自签名证书的获取
- 该文将会告诉你怎么获取crt证书 然后使用以下命令导出cer
$ openssl x509 -in demo.crt -out demo.cer -outform der
-
将crt文件双击导入到钥匙串(KeyChain)中,然后右键导出为cer文件即可
-
访问拥有自签名证书的网站,在提醒安全页面,信任并访问它.然后在查看钥匙串,你将发现那个证书已经在钥匙串中,之后右键导出为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)
}
}