Ответ
Работа с самоподписанными сертификатами требует настройки URLSession для обработки SSL-рукопожатия в обход стандартной проверки доверенных центров сертификации (CA).
Основной подход — использование делегата URLSession:
- Реализовать метод
urlSession(_:didReceive:completionHandler:). - Принять (
useCredential) или отклонить (cancelAuthenticationChallenge) сертификат на основе кастомной логики.
Пример: Принятие конкретного самоподписанного сертификата из бандла
class SSLPinningDelegate: NSObject, URLSessionDelegate {
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust,
let serverTrust = challenge.protectionSpace.serverTrust else {
completionHandler(.performDefaultHandling, nil)
return
}
// 1. Загружаем локальный сертификат
guard let certPath = Bundle.main.path(forResource: "my_server", ofType: "der"),
let localCertData = try? Data(contentsOf: URL(fileURLWithPath: certPath)) else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
// 2. Извлекаем удаленный сертификат
let remoteCert = SecTrustGetCertificateAtIndex(serverTrust, 0)
let remoteCertData = SecCertificateCopyData(remoteCert!) as Data
// 3. Сравниваем данные сертификатов (пиннинг)
if localCertData == remoteCertData {
let credential = URLCredential(trust: serverTrust)
completionHandler(.useCredential, credential)
} else {
completionHandler(.cancelAuthenticationChallenge, nil)
}
}
}
// Использование
let delegate = SSLPinningDelegate()
let session = URLSession(configuration: .default, delegate: delegate, delegateQueue: nil)
Ключевые моменты и предупреждения:
- ⚠️ Безопасность: Такой подход ослабляет защиту и должен использоваться только для тестирования (dev/staging) или внутри защищенных корпоративных сетей.
- Пиннинг (Pinning): Для продакшена рекомендуется пиннинг публичных ключей или сертификатов от доверенных CA, а не использование самоподписанных.
- Info.plist: Для iOS 9+ может потребоваться отключение ATS (
NSAppTransportSecurity) для доменов с такими сертификатами, что также является плохой практикой.