certificatesInBundle不附加自签名证书

时间:2016-01-06 10:14:08

标签: ios ssl https ssl-certificate alamofire

在我的情况下,使用便捷方法ServerTrustPolicy.certificatesInBundle()似乎无法正常使用

// MARK: - Bundle Location

/**
    Returns all certificates within the given bundle with a `.cer` file extension.

    - parameter bundle: The bundle to search for all `.cer` files.

    - returns: All certificates within the given bundle.
*/
public static func certificatesInBundle(bundle: NSBundle = NSBundle.mainBundle()) -> [SecCertificate] {
    var certificates: [SecCertificate] = []

    let paths = Set([".cer", ".CER", ".crt", ".CRT", ".der", ".DER"].map { fileExtension in
        bundle.pathsForResourcesOfType(fileExtension, inDirectory: nil)
    }.flatten())

    for path in paths {
        if let
            certificateData = NSData(contentsOfFile: path),   // <-- we get the data of the certificate in bundle 
            certificate = SecCertificateCreateWithData(nil, certificateData)  // <-- The problem is here, the certificate is not set neither errors.
        {
            certificates.append(certificate)  // <-- this doesn't run
        }
    }

    return certificates
}

可能必须使用自签名证书的格式。我完全使用了这篇博文中的#tip 5。 Five Tips for Using Self Signed SSL Certificates with iOS

问题是SecCertificateCreateWithData方法的局限性以及哪些证书格式可以接受?更好的地方我可以在哪里阅读有关这一特定问题的更多信息。

我的代码似乎是正确的,没什么特别的,可能是最常用的代码段之一:P

let defaultManager:Alamofire.Manager = {

    let serverTrustPolicies: [String: ServerTrustPolicy] = [
        "localhost": .PinCertificates(
            certificates: ServerTrustPolicy.certificatesInBundle(),
            validateCertificateChain: true,
            validateHost: true
        )
    ]

    let configuration = NSURLSessionConfiguration.ephemeralSessionConfiguration()
    configuration.HTTPAdditionalHeaders = Alamofire.Manager.defaultHTTPHeaders


    return Alamofire.Manager(
        configuration: configuration,
        serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
    )
}()

3 个答案:

答案 0 :(得分:2)

SecCertificateCreateWithData返回nil的最可能原因是文件是PEM而不是DER格式。

根据documentation,数据应包含

  

X.509的DER(可分辨编码规则)表示   证书

如果您的数据以“----- BEGIN ...”开头,那么格式错误。使用OpenSSL可以将PEM转换为DER(反之亦然) - 这是一个方便的参考https://www.sslshopper.com/article-most-common-openssl-commands.html

此外,如果是自签名证书(由“localhost”判断),则validateCertificateChain属性应为false。否则,请求将失败并显示“已取消”的NSError。

此外,从iOS9开始,App Transport Security设置应设置为允许任意加载(在Info.plist中)。这是唯一允许您的应用评估自签名证书的设置。没有它,Alamofire信任政策机制就没有机会参与其中。

答案 1 :(得分:2)

我有类似的问题。 Alamofire无法找到我的证书,ServerTrustPolicy.certificatesInBundle()方法没有返回任何内容。

问题在于,当我将证书拖入我的Xcode项目时,我没有选择&#34;添加到目标:MyProjectName&#34;。

enter image description here

答案 2 :(得分:0)

确保以格式下载证书并正确添加到项目中。

之后定义一个静态SessionManager,如下所述

public static let sharedManager: SessionManager = {
    let serverTrustPolicies: [String: ServerTrustPolicy] = [
        "subdomain.domain.com": .pinCertificates(
            certificates: ServerTrustPolicy.certificates(),
            validateCertificateChain: false,
            validateHost: true
        ),
        "insecure.expired-apis.com": .disableEvaluation
    ]


    let manager = Alamofire.SessionManager(serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies))

    return manager
}()

然后你可以调用上面的sharedManager:

YourHttpClassName.sharedManager.request(url, method: .get, headers: headers).response { response in

            print("Request: \(response.request)")
            print("Response: \(response.response)")
            print("Error: \(response.error)")

            debugPrint(response)


        }

它可以与您的自签名证书一起使用。