iOS 中HTTPS 的使用

謠言四起,大限將至。各種謠言皆因蘋果開發(fā)者大會開始,從那個時間開始,都說2017年1月1日為HPPTS即將開始的日子。從此大航海時代就要開始了。從此就成了我揮之不去的心魔,嚇得本大少和服務(wù)器端調(diào)呀調(diào)??偹阏{(diào)好了。好吧,我們聊聊HTTPS。

一、HTTPS

HTTPS(全稱:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全為目標的HTTP通道,簡單講是HTTP的安全版。即HTTP下加入SSL層,HTTPS的安全基礎(chǔ)是SSL,因此加密的詳細內(nèi)容就需要SSL。 它是一個URI scheme(抽象標識符體系),句法類同http:體系。用于安全的HTTP數(shù)據(jù)傳輸。https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默認端口及一個加密/身份驗證層(在HTTP與TCP之間)。這個系統(tǒng)的最初研發(fā)由網(wǎng)景公司(Netscape)進行,并內(nèi)置于其瀏覽器Netscape Navigator中,提供了身份驗證與加密通訊方法。(摘自百度百科)

PKI(公鑰基礎(chǔ)設(shè)施)技術(shù)是HTTPS的基礎(chǔ),PKI與非對稱密鑰加密技術(shù)密切相關(guān),包括消息摘要、數(shù)字簽名和加密服務(wù),而數(shù)字證書以及證書機構(gòu)(CA – Certificate Authority)是PKI中的重要概念。

二、Apple CSR CER P12 mobileprovition 到底是什么

  • CSR(Certificate Signing Request)鑰匙串文件 為生成證書做基礎(chǔ),要生成CER證書必須要有CSR私鑰,此私鑰包含了用戶自己的一些信息。這個文件是保存在我們的mac的(keychain)里面的, 此文件包含了(公鑰和私鑰)

  • CER 包含了開發(fā)者信息和公鑰

  • P12 它不僅包含CER的信息,還有私鑰信息,即: P12備份文件 = CER文件 + 私鑰;所以有了這個p12就再也不用擔心證書丟失了

  • mobileprovition 包含了上述所有內(nèi)容 Certificate && App ID && Device, 這個Provisioning Profile文件會在打包時嵌入到.ipa的包里。本人理解的是 可以真機調(diào)試的憑證。

三、App Transport Security

iOS9中新增App Transport Security(簡稱ATS)特性, 主要使到原來請求的時候用到的HTTP,都轉(zhuǎn)向TLS1.2協(xié)議進行傳輸。這也意味著所有的HTTP協(xié)議都強制使用了HTTPS協(xié)議進行傳輸。
一般我們?nèi)绻€是使用的http,不更新的話,可通過在 Info.plist 中聲明,倒退回不安全的網(wǎng)絡(luò)請求


111.png

然后好像我說這么多是不是一點屌用都沒用?想知道這么改不?接下來我們繼續(xù)說正事了。我這里簡單說下雙向認證的自簽名HTTPS證書的使用。放心,不坑。

準備證書

首先找后臺要一個證書(SSL證書,一般你跟后臺說要弄https,然后讓他給你個證書,他就知道了),
我們需要的是.cer的證書。但是后臺可能給我們的是.crt的證書。
我們需要轉(zhuǎn)換一下:打開終端 -> cd到.crt證書路徑 -> 輸入openssl x509 -in 你的證書.crt -out 你的證書.cer -outform der
證書就準備好了,拖入工程,記得選copy。一般叫做servicer.cer
--此段引用自大神vision_colion的文章,他文章里面有單向認證的哦。
然后我們還得需要一個client.p12證書.還是問服務(wù)器端給。

屏幕快照 2016-12-15 下午2.45.30.png

屏幕快照 2016-12-15 下午2.47.06.png
//AFNetWoking3.0以上適用
- (void)testAFNetWorking{

 NSString *certFilePath = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"cer"];
 NSData *certData = [NSData dataWithContentsOfFile:certFilePath];
 NSSet *certSet = [NSSet setWithObject:certData];
 AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:certSet];
 policy.allowInvalidCertificates = YES;
 policy.validatesDomainName = NO;

 _manager = [AFHTTPSessionManager manager];
 _manager.securityPolicy = policy;
 _manager.requestSerializer = [AFHTTPRequestSerializer serializer];
 _manager.responseSerializer = [AFHTTPResponseSerializer serializer];
 _manager.responseSerializer.acceptableContentTypes =  [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html", nil];
 //    [manager.securityPolicy setAllowInvalidCertificates:YES];
 //關(guān)閉緩存避免干擾測試r
 _manager.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
 [_manager setSessionDidBecomeInvalidBlock:^(NSURLSession * _Nonnull session, NSError * _Nonnull error) {
 NSLog(@"setSessionDidBecomeInvalidBlock");
 }];
 __weak typeof(self)weakSelf = self;
 [_manager setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession*session, NSURLAuthenticationChallenge *challenge, NSURLCredential *__autoreleasing*_credential) {
 NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
 __autoreleasing NSURLCredential *credential;
 if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
 if([weakSelf.manager.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
 credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
 if(credential) {
 disposition =NSURLSessionAuthChallengeUseCredential;
 } else {
 disposition =NSURLSessionAuthChallengePerformDefaultHandling;
 }
 } else {
 disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
 }
 } else {
 // client authentication
 SecIdentityRef identity = NULL;
 SecTrustRef trust = NULL;
 NSString *p12 = [[NSBundle mainBundle] pathForResource:@"client"ofType:@"p12"];
 NSFileManager *fileManager =[NSFileManager defaultManager];
 
 if(![fileManager fileExistsAtPath:p12])
 {
 NSLog(@"client.p12:not exist");
 }
 else
 {
 NSData *PKCS12Data = [NSData dataWithContentsOfFile:p12];
 
 if ([[weakSelf class]extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12Data])
 {
 SecCertificateRef certificate = NULL;
 SecIdentityCopyCertificate(identity, &certificate);
 const void*certs[] = {certificate};
 CFArrayRef certArray =CFArrayCreate(kCFAllocatorDefault, certs,1,NULL);
 credential =[NSURLCredential credentialWithIdentity:identity certificates:(__bridge  NSArray*)certArray persistence:NSURLCredentialPersistencePermanent];
 disposition =NSURLSessionAuthChallengeUseCredential;
 }
 }
 }
 *_credential = credential;
 return disposition;
 }];

[_manager POST:@"https://192.168.0.51/dw-api-V2.0/user/login.p" parameters:@{@"yhzh":@"18639398700",@"infoMap":@"g+bc4UTf3wHjabyKW+RYqcervD+/HSJXFIRKdVCQYldN5j85x//6eVUUZsidGrUpE+MJCvHdo7/E4EjNT+hjvnYa5qJ9ep0maOWfvq6AkIinjjc9cQJ0cfEAsg2LnV17hJKi3hCRrjbQJfAqUB2C3IetHK9Gg0voOmcTK2IA1J/V+KRcCtb1XncXDxVnXiUT/qBIQKPEg3/dt5ISLHpdXQ=="} progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
    NSString *message = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
    NSLog(@"%@",message);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    NSLog(@"%@",error);
}];
}

//驗證你P12證書的
+ (BOOL)extractIdentity:(SecIdentityRef*)outIdentity andTrust:(SecTrustRef *)outTrust fromPKCS12Data:(NSData *)inPKCS12Data {
    OSStatus securityError = errSecSuccess;
    //client certificate password 你的p12密碼
    NSDictionary*optionsDictionary = [NSDictionary dictionaryWithObject:@"123456"
                                                                 forKey:(__bridge id)kSecImportExportPassphrase];
    
    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
    securityError = SecPKCS12Import((__bridge CFDataRef)inPKCS12Data,(__bridge CFDictionaryRef)optionsDictionary,&items);
    
    if(securityError == 0) {
        CFDictionaryRef myIdentityAndTrust =CFArrayGetValueAtIndex(items,0);
        const void*tempIdentity =NULL;
        tempIdentity= CFDictionaryGetValue (myIdentityAndTrust,kSecImportItemIdentity);
        *outIdentity = (SecIdentityRef)tempIdentity;
        const void*tempTrust =NULL;
        tempTrust = CFDictionaryGetValue(myIdentityAndTrust,kSecImportItemTrust);
        *outTrust = (SecTrustRef)tempTrust;
    } else {
        NSLog(@"Failedwith error code %d",(int)securityError);
        return NO;
    }
    return YES;
}

參考文檔

蘋果官方文檔
lanp74的博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容