简体   繁体   中英

How to add ssl certificate pinning in ios app swift4 using alamofire manager?

I have problem on ssl certificate pinning in my ios app, what I want is add ssl pinning certificate to all requests using alamofire, so below is my code of the alamofire manager, when I run the app I always get this error:

load failed with error Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLStringKey= https://myWebsite.com/token , NSErrorFailingURLKey= https://myWebsite.com/token , _NSURLErrorRelatedURLSessionTaskErrorKey=( "LocalDataTask .<1>" ), _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask .<1>, NSLocalizedDescription=cancelled} [-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)
        }

    }

  }

}

My code was like this, see code below, and it was working, but I want certificate pinning for security so I add the things(Like sessionManager, init(),enableCertificatePinning() and getCertificates()) in the above code and after that its not working

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)
        }

    }

  }

}

I added the certificate to my project by drag and drop it inside the project, please help, I feel my code has some mistakes thanks in advance

Error -999 is most commonly seen when your SessionManager is deinit 'd while being used, causing all of your requests to be cancelled. From your code its looks like you're not using the sessionManager variable you've created with your custom ServerTrustPolicy at all and even if you were it's likely that whatever instance of AFManager you've created is going out of scope, causing the deinit .

You may use sessionManager , I use this class below, it creates array of certificates from your bundle;

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)
        )


    }
}

Then I do request like that,

     //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

By the way don't forget to create your networkManager object

var networkManager = NetworkManager.sharedInstance

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM