Swift iOS Client Certificate Authentication

前端 未结 4 1235
迷失自我
迷失自我 2020-12-31 10:01

The web service I want to consume requires a client certificate. How can I send my certificate to it?

To further elaborate I don\'t understand how to create the

4条回答
  •  醉梦人生
    2020-12-31 10:07

    In order to respond to the authentication challenge you need to extract the identity from your client certificate.

    struct IdentityAndTrust {
    
        var identityRef:SecIdentityRef
        var trust:SecTrustRef
        var certArray:NSArray
    }
    
    func extractIdentity(certData:NSData, certPassword:String) -> IdentityAndTrust {
    
        var identityAndTrust:IdentityAndTrust!
        var securityError:OSStatus = errSecSuccess
    
        var items:Unmanaged?
        let certOptions:CFDictionary = [ kSecImportExportPassphrase.takeRetainedValue() as String: certPassword ];
    
        // import certificate to read its entries
        securityError = SecPKCS12Import(certData, certOptions, &items);
    
        if securityError == errSecSuccess {
    
            let certItems:CFArray = items?.takeUnretainedValue() as CFArray!;
            let certItemsArray:Array = certItems as Array
            let dict:AnyObject? = certItemsArray.first;
    
            if let certEntry:Dictionary = dict as? Dictionary {
    
                // grab the identity
                let identityPointer:AnyObject? = certEntry["identity"];
                let secIdentityRef:SecIdentityRef = identityPointer as! SecIdentityRef!;
    
                // grab the trust
                let trustPointer:AnyObject? = certEntry["trust"];
                let trustRef:SecTrustRef = trustPointer as! SecTrustRef;
    
                // grab the certificate chain
                var certRef:Unmanaged?
                SecIdentityCopyCertificate(secIdentityRef, &certRef);
                let certArray:NSMutableArray = NSMutableArray();
                certArray.addObject(certRef?.takeRetainedValue() as SecCertificateRef!);
    
                identityAndTrust = IdentityAndTrust(identityRef: secIdentityRef, trust: trustRef, certArray: certArray);
            }
        }
    
        return identityAndTrust;
    }
    

    In NSURLSessionDelegate respond to the authentication challenge like this:

    public func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
    
        let bundle:NSBundle = NSBundle(forClass: self.dynamicType);
        let bundleCertPath:NSString = bundle.pathForResource("clientCertificateName", ofType: "p12")!;
        let certData:NSData = NSData(contentsOfFile: bundleCertPath as String)!;
        let identityAndTrust:IdentityAndTrust = self.certificateHelper.extractIdentity(certData, certPassword: "C00lp@assword");
    
        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate {
    
            let urlCredential:NSURLCredential = NSURLCredential(
                    identity: identityAndTrust.identityRef,
                    certificates: identityAndTrust.certArray as [AnyObject],
                    persistence: NSURLCredentialPersistence.ForSession);
    
            completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, urlCredential);
    
    
        } else {
    
            // nothing here but us chickens
        }
    }
    

提交回复
热议问题