Reputation: 674
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
Upvotes: 1
Views: 3866
Reputation: 1663
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
Upvotes: 0
Reputation: 12770
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
.
Upvotes: 1