【问题标题】:How to add ssl certificate pinning in ios app swift4 using alamofire manager?如何使用 alamofire 管理器在 ios app swift4 中添加 ssl 证书固定?
【发布时间】:2019-07-17 22:58:54
【问题描述】:

我的 ios 应用程序中的 ssl 证书固定有问题,我想要使用 alamofire 将 ssl 固定证书添加到所有请求,所以下面是我的 alamofire 管理器代码,当我运行应用程序时,我总是收到此错误:

加载失败并出现错误错误域=NSURLErrorDomain 代码=-999 “取消” UserInfo={NSErrorFailingURLStringKey=https://myWebsite.com/token, NSErrorFailingURLKey=https://myWebsite.com/token, _NSURLErrorRelatedURLSessionTaskErrorKey=( "LocalDataTask ."), _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask ., NSLocalizedDescription=取消} [-999]

class AFManager : NSObject{

private var sessionManager: SessionManager?


required override init() {
    super.init()

    enableCertificatePinning()

}

private func enableCertificatePinning() {
    let certificates = getCertificates()
    let trustPolicy = ServerTrustPolicy.pinCertificates(
        certificates: certificates,
        validateCertificateChain: true,
        validateHost: true)
    let trustPolicies = [ "myWebsite.com": trustPolicy ]
    let policyManager =  ServerTrustPolicyManager(policies: trustPolicies)
    sessionManager = SessionManager(
        configuration: .default,
        serverTrustPolicyManager: policyManager)
}

private func getCertificates() -> [SecCertificate] {
    let url = Bundle.main.url(forResource: "myWebsitessl", withExtension: "cer")!
    let localCertificate = try! Data(contentsOf: url) as CFData
    guard let certificate = SecCertificateCreateWithData(nil, localCertificate)
        else { return [] }

    return [certificate]
}



///without headers (post)
//used this to registration
class func requestPOSTURL(_ strURL : String, params : [String : AnyObject]?, success:@escaping (JSON) -> Void, failure:@escaping (Error) -> Void){
    URLCache.shared.removeAllCachedResponses()
    self.init().sessionManager?.request(strURL, method: .post, parameters: params, encoding: URLEncoding.httpBody).responseJSON { (responseObject) -> Void in

        //print(responseObject)

        if responseObject.result.isSuccess {
            let resJson = JSON(responseObject.result.value!)
            success(resJson)
        }
        if responseObject.result.isFailure {
            let error : Error = responseObject.result.error!
            failure(error)
        }
    }
}


///// response string (post)
//used this in login // used in change password
class func strRequestPOSTURL(_ strURL : String, params : [String : String]?, headers : [String : String]?, success:@escaping (JSON) -> Void, failure:@escaping (Error) -> Void){
    URLCache.shared.removeAllCachedResponses()
    self.init().sessionManager?.request(strURL, method: .post, parameters: params, encoding: URLEncoding.httpBody, headers: headers).responseJSON { (response) in
        //print(response)

        if response.result.isSuccess {
            let resJson = JSON(response.result.value!)
            success(resJson)
        }
        if response.result.isFailure {
            let error : Error = response.result.error!

            failure(error)
        }

    }

  }

}

我的代码是这样的,请参见下面的代码,它正在工作,但我想要证书固定以确保安全,所以我在上面的代码中添加了东西(如 sessionManager、init()、enableCertificatePinning() 和 getCertificates())然后它就不起作用了

class AFManager : NSObject{


///without headers (post)
//used this to registration
class func requestPOSTURL(_ strURL : String, params : [String : AnyObject]?, success:@escaping (JSON) -> Void, failure:@escaping (Error) -> Void){
    URLCache.shared.removeAllCachedResponses()
    Alamofire.request(strURL, method: .post, parameters: params, encoding: URLEncoding.httpBody).responseJSON { (responseObject) -> Void in

        //print(responseObject)

        if responseObject.result.isSuccess {
            let resJson = JSON(responseObject.result.value!)
            success(resJson)
        }
        if responseObject.result.isFailure {
            let error : Error = responseObject.result.error!
            failure(error)
        }
    }
}


///// response string (post)
//used this in login // used in change password
class func strRequestPOSTURL(_ strURL : String, params : [String : String]?, headers : [String : String]?, success:@escaping (JSON) -> Void, failure:@escaping (Error) -> Void){
    URLCache.shared.removeAllCachedResponses()
    Alamofire.request(strURL, method: .post, parameters: params, encoding: URLEncoding.httpBody, headers: headers).responseJSON { (response) in
        //print(response)

        if response.result.isSuccess {
            let resJson = JSON(response.result.value!)
            success(resJson)
        }
        if response.result.isFailure {
            let error : Error = response.result.error!

            failure(error)
        }

    }

  }

}

我通过在项目中拖放将证书添加到我的项目中,请帮助,我觉得我的代码有一些错误 在此先感谢

【问题讨论】:

    标签: ios swift ssl-certificate alamofire certificate-pinning


    【解决方案1】:

    错误-999 最常见的情况是您的SessionManager 在使用时是deinit,导致您的所有请求都被取消。从您的代码看来,您根本没有使用您使用自定义 ServerTrustPolicy 创建的 sessionManager 变量,即使您创建的 AFManager 的任何实例都可能已经失效范围,导致deinit

    【讨论】:

    • 谢谢你的重播,我理解你的意思,但我怎么能用我的代码做到这一点
    • 最常见的是使用单例来完成,但依赖注入也可以做到,只要注入器的生命周期比您的请求长。
    【解决方案2】:

    你可以使用sessionManager,我在下面使用这个类,它从你的包中创建证书数组;

    class NetworkManager
    {
        static let sharedInstance = NetworkManager()
        var manager: SessionManager?
    
        init()
        {
            var certificates = ServerTrustPolicy.certificates(in: Bundle.main)
    
            let serverTrustPolicies: [String: ServerTrustPolicy] = [
                "yourUrl.com": .pinCertificates(
                    certificates: ServerTrustPolicy.certificates(in: Bundle.main),
                    validateCertificateChain: true,
                    validateHost: true
                )
            ]
    
            manager = SessionManager(
                serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
            )
    
    
        }
    }
    

    那我就这样要求了,

         //request depends on your needs. Post, get etc..
            var request = URLRequest(url: yourUrl)
            request.httpMethod = HTTPMethod.get.rawValue
            request.setValue("application/json; charset=UTF-8", forHTTPHeaderField: "Content-Type")
    
            networkManager.manager!.request(request).responseJSON
    

    顺便说一句,不要忘记创建你的 networkManager 对象

    var networkManager = NetworkManager.sharedInstance
    

    【讨论】:

      猜你喜欢
      • 2020-06-01
      • 2016-04-09
      • 1970-01-01
      • 2017-05-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-28
      相关资源
      最近更新 更多