Created
February 9, 2017 09:42
-
-
Save VictorZhang2014/1d4903b1c5f260d9cae6a007fb53bebe to your computer and use it in GitHub Desktop.
NSURLSession implements SSL/TLS request was written by Objective-C.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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