Alamofire 5 альтернатива sessionDidReceiveChallenge

Я только что перешел на Alamofire 5.

Раньше я использовал URLSession и Certificate Pinner, а для решения проблемы аутентификации я использовал метод делегированияURLSessionDelegate с хеш-значениями

func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge,
                completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
    print("being challanged! for \(challenge.protectionSpace.host)")
    guard let trust = challenge.protectionSpace.serverTrust else {
        print("invalid trust!")
        completionHandler(.cancelAuthenticationChallenge, nil)
        return
    }

    let credential = URLCredential(trust: trust)

    let pinner = setupCertificatePinner(host: challenge.protectionSpace.host)

    if (!pinner.validateCertificateTrustChain(trust)) {
        print("failed: invalid certificate chain!")
        challenge.sender?.cancel(challenge)
    }

    if (pinner.validateTrustPublicKeys(trust)) {
        completionHandler(.useCredential, credential)
    } else {
        didPinningFailed = true
        print("couldn't validate trust for \(challenge.protectionSpace.host)")
        completionHandler(.cancelAuthenticationChallenge, nil)
    }

}

Перебравшись на Аламофайр 5, способа нет sessionDidReceiveChallenge который был доступен в более ранней версии.

Я попытался:

private let session: Session = {
    let manager = ServerTrustManager(allHostsMustBeEvaluated: true, evaluators:
        ["devDomain.com": DisabledTrustEvaluator(),
         "prodDomain.com": PublicKeysTrustEvaluator()])
    let configuration = URLSessionConfiguration.af.default

    return Session(configuration: configuration, serverTrustManager: manager)
}()

Но получаю ошибку:

Error Domain=Alamofire.AFError Code=11 "Server trust evaluation failed due to reason: No public keys were found or provided for evaluation."

Обновление:я все равно предпочел бы анализировать его, используя только 256 отпечатков пальцев, поскольку мы получаем домены и их хэши в первом вызове api.

2 ответа

Решение

Сначала вам понадобится ServerTrustEvaluating который обрабатывает сертификат, прикрепляющий простой инструмент, будет чем-то похожим на

public final class CertificatePinnerTrustEvaluator: ServerTrustEvaluating {

    public init() {}

    func setupCertificatePinner(host: String) -> CertificatePinner {

        //get the CertificatePinner
    }

    public func evaluate(_ trust: SecTrust, forHost host: String) throws {

        let pinner = setupCertificatePinner(host: host)

        if (!pinner.validateCertificateTrustChain(trust)) {
            print("failed: invalid certificate chain!")
            throw AFError.serverTrustEvaluationFailed(reason: .noCertificatesFound)
        }

        if (!pinner.validateTrustPublicKeys(trust)) {
            print ("couldn't validate trust for \(host)")

            throw AFError.serverTrustEvaluationFailed(reason: .noCertificatesFound)
        }
    }
}

Чтобы иметь возможность использовать тот же оценщик, я бы предложил создать подкласс ServerTrustManager чтобы вернуть тот же оценщик, я сделал это так:

class CertificatePinnerServerTrustManager: ServerTrustManager {

    let evaluator = CertificatePinnerTrustEvaluator()

    init() {
        super.init(allHostsMustBeEvaluated: true, evaluators: [:])
    }

    open override func serverTrustEvaluator(forHost host: String) throws -> ServerTrustEvaluating? {

        return evaluator
    }
}

после этого вы должны быть готовы к работе, создав сеанс и передав ему менеджер

private let session: Session = {

    let trustManager = CertificatePinnerServerTrustManager()

    return Session(serverTrustManager: trustManager)
}()

Моя ссылка была методом urlSession(_:task:didReceive:completionHandler:) в исходнике Alamofire в SessionDelegate.swift в строке 86 (Alamofire V5.2.1)

Если вы хотите закрепить с помощью открытых ключей, вам необходимо предоставить сертификаты, из которых будет анализироваться эти открытые ключи в пакете вашего приложения, или иным образом предоставить их PublicKeysTrustEvaluator.

Другие вопросы по тегам