Sai Reddy 的解决方案允许您接受自签名证书,如果它具有完整的链路,则也接受其他证书。
Marcus Leon 的解决方案是完全覆盖 - 基本上忽略所有证书。
我更喜欢这个。
Swift 4.1,iOS 11.4.1
首先,在您的 Info.plist 文件中:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
其次,无论在何处使用您的NSURLSession,都请使用类似以下代码而不是设置为URLSession.shared:
session = URLSession(configuration: .default, delegate: APIURLSessionTaskDelegate(isSSLPinningEnabled: isSSLPinningEnabled), delegateQueue: nil)
然后添加这个类来处理固定:
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
print("*** received SESSION challenge...\(challenge)")
let trust = challenge.protectionSpace.serverTrust!
let credential = URLCredential(trust: trust)
guard isSSLPinningEnabled else {
print("*** SSL Pinning Disabled -- Using default handling.")
completionHandler(.useCredential, credential)
return
}
let myCertName = "my_certificate_to_pin"
var remoteCertMatchesPinnedCert = false
if let myCertPath = Bundle.main.path(forResource: myCertName, ofType: "der") {
if let pinnedCertData = NSData(contentsOfFile: myCertPath) {
let remoteCertData: NSData = SecCertificateCopyData(SecTrustGetCertificateAtIndex(trust, 0)!)
if remoteCertData.isEqual(to: pinnedCertData as Data) {
print("*** CERTIFICATE DATA MATCHES")
remoteCertMatchesPinnedCert = true
}
else {
print("*** MISMATCH IN CERT DATA.... :(")
}
} else {
print("*** Couldn't read pinning certificate data")
}
} else {
print("*** Couldn't load pinning certificate!")
}
if remoteCertMatchesPinnedCert {
print("*** TRUSTING CERTIFICATE")
completionHandler(.useCredential, credential)
} else {
print("NOT TRUSTING CERTIFICATE")
completionHandler(.rejectProtectionSpace, nil)
}
}
}
这个类检查您是否启用了证书固定。如果是,则完全忽略正常的证书验证,并使用我们在应用程序中包含的证书进行精确比较。通过这种方式,它
仅接受您自签名的证书,而不接受其他任何证书。
此解决方案要求您在项目中的资源文件夹中放置一个名为“
my_certificate_to_pin.der”的文件。如果您还没有资源文件夹,请添加一个。
该证书应以DER格式提供。
要为您的服务器创建自签名证书,通常会执行以下操作:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout mycert.key -out mycert.cer
这将生成两个文件 -- 一个mycert.key私钥文件和一个mycert.cer证书本身。它们都是X509格式的。对于iOS,您需要以DER格式获取证书,因此请执行以下操作:
openssl x509 -outform der -in mycert.cer -out my_certificate_to_pin.der
这将在iOS上生成您所需的文件。