swift 和 obj-c 完成 ssl 的寫法如下:
We can start by instantiating an NSURLSession object with the default session configuration.
Swift
self.urlSession = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: self, delegateQueue: nil)
Objective C
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
self.urlSession = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];
use the dataTaskWithURL:completionHandler: method for the SSL pinning test. The request we send will look something like this:
Swift
self.urlSession?.dataTaskWithURL(NSURL(string:self.urlTextField.text!)!, completionHandler: { (NSData data, NSURLResponse response, NSError error) Void in
// response management code
}).resume()
Objective C
[[self.urlSession dataTaskWithURL:[NSURL URLWithString:self.textField.text] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// response management code
}] resume];
implemented within the URLSession:didReceiveChallenge:completionHandler:delegatemethod. Note that, upon the creation of the NSURLSession object, we assigned self as the delegate so that this method is called on our object.
Swift
func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
let serverTrust = challenge.protectionSpace.serverTrust
let certificate = SecTrustGetCertificateAtIndex(serverTrust!, 0)
// Set SSL policies for domain name check
let policies = NSMutableArray();
policies.addObject(SecPolicyCreateSSL(true, (challenge.protectionSpace.host)))
SecTrustSetPolicies(serverTrust!, policies);
// Evaluate server certificate
var result: SecTrustResultType = 0
SecTrustEvaluate(serverTrust!, &result)
let isServerTrusted:Bool = (Int(result) == kSecTrustResultUnspecified || Int(result) == kSecTrustResultProceed)
// Get local and remote cert data
let remoteCertificateData:NSData = SecCertificateCopyData(certificate!)
let pathToCert = NSBundle.mainBundle().pathForResource(githubCert, ofType: "cer")
let localCertificate:NSData = NSData(contentsOfFile: pathToCert!)!
if (isServerTrusted && remoteCertificateData.isEqualToData(localCertificate)) {
let credential:NSURLCredential = NSURLCredential(forTrust: serverTrust!)
completionHandler(.UseCredential, credential)
} else {
completionHandler(.CancelAuthenticationChallenge, nil)
}
}
Objective C
-(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
// Get remote certificate
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0);
// Set SSL policies for domain name check
NSMutableArray *policies = [NSMutableArray array];
[policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)challenge.protectionSpace.host)];
SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies);
// Evaluate server certificate
SecTrustResultType result;
SecTrustEvaluate(serverTrust, &result);
BOOL certificateIsValid = (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed);
// Get local and remote cert data
NSData *remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate));
NSString *pathToCert = [[NSBundle mainBundle]pathForResource:@"github.com" ofType:@"cer"];
NSData *localCertificate = [NSData dataWithContentsOfFile:pathToCert];
// The pinnning check
if ([remoteCertificateData isEqualToData:localCertificate] && certificateIsValid) {
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
} else {
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, NULL);
}
}
如果不使用 local certificate:
// Get remote certificate
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
// Set SSL policies for domain name check
NSMutableArray *policies = [NSMutableArray array];
[policies addObject🙁__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)challenge.protectionSpace.host)];
SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies);
// Evaluate server certificate
SecTrustResultType result;
SecTrustEvaluate(serverTrust, &result);
BOOL certificateIsValid = (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed);
// The pinnning check
if (certificateIsValid) {
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
} else {
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, NULL);
}