如何在swift中使用证书向REST API发出请求?

时间:2018-01-31 07:40:39

标签: ios swift rest swift3 ssl-certificate

我想通过swift中的rest call api传递pfx文件。存储在本地驱动器中的pfx文件。我将在python中完成,因此示例代码在

下面
    var json=["{\"panInquiry\":{\"Header\":{\"TranID\":\"12345\",\"Corp_ID\":\"ZSA01\",\"Maker_ID\":\"\",\"Checker_ID\":\"\",\"Approver_ID\":\"\",\"Nsdl_UserID\":\"B3456789\"},\"Body\":{\"panNumbers\":[{\"pan1\":\"abba@123\"}]}}}"]


    let jsonData = try? JSONSerialization.data(withJSONObject: json)

    // create post request
    let url=URL(string:"https://dshdjksdhsjhd")


//        let pathToCert = Bundle.main.path(forResource: "mychatbot", ofType: "pfx")
//        let localCertificate:NSData = NSData(contentsOfFile: pathToCert!)!

//        var pemPath: String? = "/Users/rohitverma/Desktop/A/mychatbot.pfx"
    var request = URLRequest(url: url!)
    request.httpMethod = "POST"

    let str="ZSA:pas@12345"
    let utf8str = str.data(using: String.Encoding.utf8)
    let base64Encoded = utf8str?.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
    //print("Encoded:  base64Encoded")
    request.setValue("Basic \(base64Encoded)", forHTTPHeaderField: "Authorization")


    // insert json data to the request
    request.httpBody = jsonData

    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data, error == nil else {
            print(error?.localizedDescription ?? "No data")
            return
        }
        let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
        if let responseJSON = responseJSON as? [String: Any] {
            print(responseJSON)
        }
    }

    task.resume()
}
}

这将是一个过程,但我不知道如何通过swift中的请求传递ssl证书。 在python中,它将通过以下代码

完成
response = requests.post(url, json=json.loads(jsonstr, object_pairs_hook=OrderedDict),headers={"Authorization": "Basic %s" % b64Val},cert='C:\\Users\\lenovo\\Desktop\\mychatbot.pem', verify=True)

2 个答案:

答案 0 :(得分:2)

您必须实施URLSessionDelegate并执行以下操作:

static func getCertSession() -> URLSession {
    let sessionDelegate = MySessionDelegate()
    let conf = URLSessionConfiguration.default
    conf.requestCachePolicy = NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData
    conf.timeoutIntervalForRequest = 1000
    conf.timeoutIntervalForResource = 1000
    return URLSession.init(configuration: conf, delegate: sessionDelegate, delegateQueue: OperationQueue.main)
}

class MySessionDelegate : NSObject : URLSessionDelegate {
     public func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
            if let localCertPath = Bundle.main.url(forResource: PATH_OF_YOUR_CERT, withExtension: "pfx"),
                let localCertData = try?  Data(contentsOf: localCertPath)
            {

                let identityAndTrust:IdentityAndTrust = extractIdentity(certData: localCertData as NSData, certPassword: PASSWORD_OF_YOUR_PFX)

                if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate {

                    let urlCredential:URLCredential = URLCredential(
                        identity: identityAndTrust.identityRef,
                        certificates: identityAndTrust.certArray as [AnyObject],
                        persistence: URLCredential.Persistence.forSession);

                    completionHandler(URLSession.AuthChallengeDisposition.useCredential, urlCredential);

                    return
                }
            }

            challenge.sender?.cancel(challenge)
            completionHandler(URLSession.AuthChallengeDisposition.rejectProtectionSpace, nil)
        }
}

最后使用getCertSession().task(...)代替URLSeesion.shared.task(...)

执行您的任务

修改

public struct IdentityAndTrust {

    public var identityRef:SecIdentity
    public var trust:SecTrust
    public var certArray:NSArray
}

public func extractIdentity(certData:NSData, certPassword:String) -> IdentityAndTrust {

    var identityAndTrust:IdentityAndTrust!
    var securityError:OSStatus = errSecSuccess

    var items: CFArray?
    let certOptions: Dictionary = [ kSecImportExportPassphrase as String : certPassword ];
    // import certificate to read its entries
    securityError = SecPKCS12Import(certData, certOptions as CFDictionary, &items);
    if securityError == errSecSuccess {

        let certItems:CFArray = items as CFArray!;
        let certItemsArray:Array = certItems as Array
        let dict:AnyObject? = certItemsArray.first;

        if let certEntry:Dictionary = dict as? Dictionary<String, AnyObject> {

            // grab the identity
            let identityPointer:AnyObject? = certEntry["identity"];
            let secIdentityRef:SecIdentity = identityPointer as! SecIdentity!;

            // grab the trust
            let trustPointer:AnyObject? = certEntry["trust"];
            let trustRef:SecTrust = trustPointer as! SecTrust;

            // grab the certificate chain
            var certRef: SecCertificate?
            SecIdentityCopyCertificate(secIdentityRef, &certRef);
            let certArray:NSMutableArray = NSMutableArray();
            certArray.add(certRef as SecCertificate!);

            identityAndTrust = IdentityAndTrust(identityRef: secIdentityRef, trust: trustRef, certArray: certArray);
        }
    }

    return identityAndTrust;
}

答案 1 :(得分:0)

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

@IBAction func pfxcl(_ sender: Any) {
    print("Btn press")
    var json=["{\"panInquiry\":{\"Header\":{\"TranID\":\"12345\",\"Corp_ID\":\"ASXE\",\"Maker_ID\":\"\",\"Checker_ID\":\"\",\"Approver_ID\":\"\",\"Nsdl_UserID\":\"ASFD454D\"},\"Body\":{\"panNumbers\":[{\"pan1\":\"qswerf98\"}]}}}"]

    let jsonData = try? JSONSerialization.data(withJSONObject: json)

    // create post request
    let url=URL(string:"https://apideveloper.com")

    var request = URLRequest(url: url!)
    request.httpMethod = "POST"

    let str="ACZZ:password@345"
    let utf8str = str.data(using: String.Encoding.utf8)
    let base64Encoded = utf8str?.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
    //print("Encoded:  base64Encoded")
    request.setValue("Basic \(base64Encoded)", forHTTPHeaderField: "Authorization")


    request.httpBody = jsonData

    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data, error == nil else {
            print(error?.localizedDescription ?? "No data")
            return
        }
        let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
        if let responseJSON = responseJSON as? [String: Any] {
            print(responseJSON)
        }
    }

    task.resume()

    class MySessionDelegate : NSObject , URLSessionDelegate  {
        func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
            if let localCertPath = Bundle.main.url(forResource: "mychatbot", withExtension: "pfx"),
                let localCertData = try?  Data(contentsOf: localCertPath)
            {

                let identityAndTrust : IdentityAndTrust = extractIdentity(certData: localCertData as NSData, certPassword: "ACZZ:password@345")

                if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate {

                    let urlCredential:URLCredential = URLCredential(
                        identity: identityAndTrust.identityRef,
                        certificates: identityAndTrust.certArray as [AnyObject],
                        persistence: URLCredential.Persistence.forSession);

                    completionHandler(URLSession.AuthChallengeDisposition.useCredential, urlCredential);

                    return
                }
            }

            challenge.sender?.cancel(challenge)
            completionHandler(URLSession.AuthChallengeDisposition.rejectProtectionSpace, nil)
        }

        func getCertSession() -> URLSession {
            let sessionDelegate = MySessionDelegate()
            let conf = URLSessionConfiguration.default
            conf.requestCachePolicy = NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData
            conf.timeoutIntervalForRequest = 1000
            conf.timeoutIntervalForResource = 1000
            return URLSession.init(configuration: conf, delegate: sessionDelegate as! URLSessionDelegate, delegateQueue: OperationQueue.main)
        }


        struct IdentityAndTrust {
            public var identityRef:SecIdentity
            public var trust:SecTrust
            public var certArray:NSArray
        }

        func extractIdentity(certData:NSData, certPassword:String) -> IdentityAndTrust {

            var identityAndTrust:IdentityAndTrust!
            var securityError:OSStatus = errSecSuccess

            var items: CFArray?
            let certOptions: Dictionary = [ kSecImportExportPassphrase as String : certPassword ];

            securityError = SecPKCS12Import(certData, certOptions as CFDictionary, &items);
            if securityError == errSecSuccess {

                let certItems:CFArray = items as CFArray!;
                let certItemsArray:Array = certItems as Array
                let dict:AnyObject? = certItemsArray.first;

                if let certEntry:Dictionary = dict as? Dictionary<String, AnyObject> {


                    let identityPointer:AnyObject? = certEntry["identity"];
                    let secIdentityRef:SecIdentity = identityPointer as! SecIdentity!;


                    let trustPointer:AnyObject? = certEntry["trust"];
                    let trustRef:SecTrust = trustPointer as! SecTrust;


                    var certRef: SecCertificate?
                    SecIdentityCopyCertificate(secIdentityRef, &certRef);
                    let certArray:NSMutableArray = NSMutableArray();
                    certArray.add(certRef as SecCertificate!);

                    identityAndTrust = IdentityAndTrust(identityRef: secIdentityRef, trust: trustRef, certArray: certArray);
                }
            }

            return identityAndTrust;
        }

    }

}


}