Skip to content

Instantly share code, notes, and snippets.

@VictorZhang2014
Created February 9, 2017 09:42
Show Gist options
  • Save VictorZhang2014/1d4903b1c5f260d9cae6a007fb53bebe to your computer and use it in GitHub Desktop.
Save VictorZhang2014/1d4903b1c5f260d9cae6a007fb53bebe to your computer and use it in GitHub Desktop.
NSURLSession implements SSL/TLS request was written by Objective-C.
#import "ViewController.h"
@interface ViewController ()<NSURLSessionDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSURL *url = [NSURL URLWithString:@"https://www.domain.com/Home/LoginWithPass"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
NSURLSessionDataTask *data = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@ %ld", str, (long)httpResponse.statusCode);
}];
[data resume];
}
/*
摘要:适用于自签名证书,DV,OV,EV类型的证书
作用:1.单向认证(One-way Authentication)
此delegate方法会有一次调用,是NSURLAuthenticationMethodServerTrust
2.双向认证(Bidirectional Authentication,或者Mutual Authentication,也有Two-way Authentication)
此delegate方法会有两次调用,分别是NSURLAuthenticationMethodServerTrust和NSURLAuthenticationMethodClientCertificate
*/
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler
{
//证书的处理方式
NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
NSURLCredential *credential = nil;
//判断服务器返回的证书是否是服务器信任的
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { //受信任的
//获取服务器返回的证书
credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
if (credential) {
disposition = NSURLSessionAuthChallengeUseCredential;
} else {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
} else {
//读取证书的私钥
NSString *thePath = [[NSBundle mainBundle] pathForResource:@"webtest_ssl_Certificate" ofType:@"p12"];
NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
CFDataRef inPKCS12Data = (CFDataRef)CFBridgingRetain(PKCS12Data);
SecIdentityRef identity = nil;
//读取p12证书的私钥内容
OSStatus result = [self extractP12Data:inPKCS12Data toIdentity:&identity];
if(result != errSecSuccess){
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
return;
}
SecCertificateRef certificate = NULL;
SecIdentityCopyCertificate(identity, &certificate);
const void *certs[] = {certificate};
CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL);
credential = [NSURLCredential credentialWithIdentity:identity certificates:(NSArray*)CFBridgingRelease(certArray) persistence:NSURLCredentialPersistencePermanent];
disposition = NSURLSessionAuthChallengeUseCredential;
}
//安装证书(即导入到iPhone的KeyChain)
if (completionHandler) {
completionHandler(disposition, credential);
}
}
- (OSStatus)extractP12Data:(CFDataRef)inP12Data toIdentity:(SecIdentityRef *)identity {
OSStatus securityError = errSecSuccess;
CFStringRef password = CFSTR("Your Cert Password");
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
securityError = SecPKCS12Import(inP12Data, options, &items);
if (securityError == errSecSuccess) {
CFDictionaryRef ident = CFArrayGetValueAtIndex(items, 0);
const void *tempIdentity = NULL;
tempIdentity = CFDictionaryGetValue(ident, kSecImportItemIdentity);
*identity = (SecIdentityRef)tempIdentity;
}
if (options) CFRelease(options);
if (password) CFRelease(password);
return securityError;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment