Ios Alamofire中的证书固定

Ios Alamofire中的证书固定,ios,swift,alamofire,pinning,Ios,Swift,Alamofire,Pinning,我正在创建一个访问HTTPS web服务的iPad应用程序。我想实现钉扎,但遇到了一些问题 此类创建Alamofire Manager(主要取自文档): 此函数进行以下调用: static let networkManager = NetworkManager() public static func testPinning() { networkManager.manager!.request(.GET, "https://www.google.co.uk").response {

我正在创建一个访问HTTPS web服务的iPad应用程序。我想实现钉扎,但遇到了一些问题

此类创建Alamofire Manager(主要取自文档):

此函数进行以下调用:

static let networkManager = NetworkManager()

public static func testPinning() {
    networkManager.manager!.request(.GET, "https://www.google.co.uk").response { response in
        if response.1 != nil {
            print("Success")
            print(response.1)
            print(response.1?.statusCode)
        } else {
            print("Error")
            print(response.3)
        }
    }
}
项目中的,并显示在“目标>构建阶段>复制捆绑资源”下

每次发出请求时(从
testPinning()
中的else块),我当前都会收到以下错误:


因此,问题是证书以错误的格式保存


ServerTrustPolicy.certificatesInBundle()
根据扩展列表查找捆绑包中的所有证书,然后尝试使用
SecCertificateCreateWithData
加载它们。根据其文档,此功能:

如果数据参数中传递的数据无效,则返回NULL DER编码的X.509证书


在Firefox中导出证书时,文件浏览器底部会弹出一个“格式”窗口。选择“X.509证书(DER)”,您将获得一份格式正确的证书。首先,您需要下载该证书。最好的方法是在Firefox浏览器上下载证书

步骤1

转到您的网页/API并单击锁定图标以获取证书

步骤2

单击查看证书

步骤3

单击证书字段选项卡的第一部分,然后单击导出

步骤4

选择格式:-DER

步骤5

将文件拖放到XCode项目中

步骤6

在“目标>生成阶段>复制捆绑资源”下添加证书

步骤7

添加网络管理器文件。将您的URL替换为google.com

 import Foundation
 import Alamofire
 import SwiftyJSON

 class MYPNetworkManager {


     var Manager: SessionManager?

     init() {
         let serverTrustPolicies: [String: ServerTrustPolicy] = [
             "https://google.com": .pinCertificates(
                 certificates: ServerTrustPolicy.certificates(),
                 validateCertificateChain: true,
                 validateHost: true
             ),
             "insecure.expired-apis.com": .disableEvaluation
         ]

         Manager = SessionManager(
             serverTrustPolicyManager: ServerTrustPolicyManager(policies: 
 serverTrustPolicies)
         )

     }
 }
步骤8

添加一个文件以获取会话管理器

import Foundation
import Alamofire
import SwiftyJSON

class APIPinning {

    private static let NetworkManager = MYPNetworkManager()

    public static func getManager() -> SessionManager {
        return NetworkManager.Manager!
    }
 }
步骤9

在Alamofire上使用此会话管理器 例如:-


在Alamofire版本+5之后,有一个很大的变化,我将在这里列出我做了什么来进行证书固定。我的目标是莫亚,因为莫亚是阿拉莫菲尔之上的一层,阿拉莫菲尔的工作应该与莫亚合作

首先,要获取服务器证书,需要在浏览器中打开它,然后单击锁定图标 然后,您需要单击屏幕截图所示的证书。 之后,您需要将此证书拖到桌面或任何下载位置,请查看下面的屏幕截图。 然后,您需要使用Xcode检查屏幕截图中将文件添加到项目中。 以下是我的Alamofire代码:

var session: Session!

class ViewController: UIViewController {

func testPinning() {


let evaluators: [String: ServerTrustEvaluating] = [
    "stackoverflow.com": PublicKeysTrustEvaluator()
]

let manager = ServerTrustManager(evaluators: evaluators)

session = Session(serverTrustManager: manager)


session
    .request("https://stackoverflow.com/questions/34611112/certificate-pinning-in-alamofire/55902588#55902588", method: .get)
    .validate()
    .response(completionHandler: { [weak self] response in
        switch response.result {
        case .success:
            print(response.data)
        case .failure(let error):
            switch error {
            case .serverTrustEvaluationFailed(let reason):
                // The reason here is a place where you might fine-tune your
                // error handling and possibly deduce if it's an actualy MITM
                // or just another error, like certificate issue.
                //
                // In this case, this will show `noRequiredEvaluator` if you try
                // testing against a domain not in the evaluators list which is
                // the closest I'm willing to setting up a MITM. In production,
                // it will most likely be one of the other evaluation errors.
                print(reason)
            default:
                print("default")
            }
        }
    })

}
对于Moya,您需要将该会话添加到您的Moya提供商

    let evaluators: [String: ServerTrustEvaluating] = [
    "stackoverflow.com": PublicKeysTrustEvaluator()
]

let manager = ServerTrustManager(evaluators: evaluators)

session = Session(serverTrustManager: manager)



let provider = MoyaProvider<YourStackOVerflowProvider>(
    session: session
)


provider.request(.pluginManger) { response in
    switch response {
    case .failure(let err):
        print(err)
    case .success(let response):
        print(response)
    }
}
let求值器:[字符串:ServerTrustEvaluating]=[
“stackoverflow.com”:PublicKeyTrustEvaluator()
]
let manager=ServerTrustManager(评估者:评估者)
会话=会话(服务器信任管理器:管理器)
let provider=MoyaProvider(
会议:会议
)
provider.request(.pluginManger){中的响应
开关响应{
案例。失败(错误):
打印(错误)
成功案例(让我们回答):
打印(答复)
}
}

您提供了什么证书?您是否已检查了
ServerTrustPolicy.certificatesInBundle()
返回的内容(即,它是否实际包含证书)?如果Google为同一个域使用多个证书,也不会太惊讶。
ServerTrustPolicy.certificatesInBundle()
返回0,我不理解。是否有一种将.cer证书添加到捆绑包中的特定方式?关于谷歌,这是一个替代我正在开发的网站的例子,但是上面的问题是一样的。你是说它返回一个空数组?该调用的返回值应该是数组,而不是数字。您可能希望尝试
NSBundle.mainBundle().pathsforsourcesoftype(“.cer”,inDirectory:nil)
以查看是否在捆绑包中找到该文件(如果是,则可能会指向证书文件内容的问题)。调用
ServerTrustPolicy.certificatesInBundle()
时日志中是否显示任何内容?是的,这是正确的,我指的是一个0值数组。仔细检查后,可以在
证书inbundle()
中找到这行代码。在for循环中,找到了证书,但第138行阻止将证书添加到数组中。我怀疑它也可能是.cer的内容,尽管它在Xcode中可以正常打开(关于如何保存证书,而不是问题中链接的方法,有什么建议吗?)。还有,我如何检查这些日志呢?在Firefox中导出证书时,文件浏览器底部会弹出一个“格式”窗口。你选择了什么格式?我认为您需要“X.509证书(DER)”(根据文档说明,“如果
data
参数中传递的数据不是有效的DER编码的X.509证书,则返回NULL”(我的重点)。
 public static func testPinning() {
NetworkManager.Manager!.request("YourURL", method: .get, encoding: URLEncoding.httpBody, headers: MConnect.headersWithToken)
    .validate()
    .responseJSON { response in

        print(response)
        switch response.result {
        case .success:

            if let value = response.result.value {
                let json = JSON(value)
                print(json)
            } else {

            }

        case .failure:
            print("Error")
        }
}
}
var session: Session!

class ViewController: UIViewController {

func testPinning() {


let evaluators: [String: ServerTrustEvaluating] = [
    "stackoverflow.com": PublicKeysTrustEvaluator()
]

let manager = ServerTrustManager(evaluators: evaluators)

session = Session(serverTrustManager: manager)


session
    .request("https://stackoverflow.com/questions/34611112/certificate-pinning-in-alamofire/55902588#55902588", method: .get)
    .validate()
    .response(completionHandler: { [weak self] response in
        switch response.result {
        case .success:
            print(response.data)
        case .failure(let error):
            switch error {
            case .serverTrustEvaluationFailed(let reason):
                // The reason here is a place where you might fine-tune your
                // error handling and possibly deduce if it's an actualy MITM
                // or just another error, like certificate issue.
                //
                // In this case, this will show `noRequiredEvaluator` if you try
                // testing against a domain not in the evaluators list which is
                // the closest I'm willing to setting up a MITM. In production,
                // it will most likely be one of the other evaluation errors.
                print(reason)
            default:
                print("default")
            }
        }
    })

}
    let evaluators: [String: ServerTrustEvaluating] = [
    "stackoverflow.com": PublicKeysTrustEvaluator()
]

let manager = ServerTrustManager(evaluators: evaluators)

session = Session(serverTrustManager: manager)



let provider = MoyaProvider<YourStackOVerflowProvider>(
    session: session
)


provider.request(.pluginManger) { response in
    switch response {
    case .failure(let err):
        print(err)
    case .success(let response):
        print(response)
    }
}