配置Https:
(一)準(zhǔn)備證書
.cer (后端提供,有可能是crt,直接改后綴為cer就行)
.p12 (后端給過(guò)來(lái)的pfx證書,里面包含公鑰私鑰,把證書導(dǎo)入鑰匙串,然后導(dǎo)出為.p12文件,帶密碼)
(二)檢查證書
1.檢查是否符合,把證書拉入項(xiàng)目根目錄,點(diǎn)擊就可以查看相關(guān)信息
2.打開(kāi)終端輸入 nscurl —ats-diagnostics —verbose https://你的域名/
然后會(huì)出現(xiàn)類似這樣的反饋,分別有TLSv1.0----TLSv1.2的測(cè)試案例返回,如果HTTPS服務(wù)器能通過(guò)ATS特性,則上面所有測(cè)試案例都是PASS;如果某一項(xiàng)的Reuslt是FAIL,就找到ATS Dictionary來(lái)查看,就能知道HTTPS服務(wù)器不滿足ATS哪個(gè)條件。
3.然后根據(jù)測(cè)試案例TLSv1.2返回的NSExceptionDomains信息配置項(xiàng)目的根.plist文件的App Transport Security Settings->Exception Domains->
【圖僅供示例,請(qǐng)根據(jù)自己的返回填寫】
(三)代碼設(shè)置,雙向認(rèn)證
{ //manager自行配置 AFHTTPSessionManager manager = nil; if ([self baseUrl] != nil) { manager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:[self baseUrl]]]; } else { manager = [AFHTTPSessionManager manager]; } manager.securityPolicy = [self getSecurityPolicy]; [manager setSessionDidBecomeInvalidBlock:^(NSURLSession * _Nonnull session, NSError * _Nonnull error) { NSLog(@"setSessionDidBecomeInvalidBlock"); }]; //客服端請(qǐng)求驗(yàn)證 重寫 setSessionDidReceiveAuthenticationChallengeBlock 方法 __weak typeof(self)weakSelf = self; [manager setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSessionsession, NSURLAuthenticationChallenge *challenge, NSURLCredential __autoreleasing_credential) { NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling; __autoreleasing NSURLCredential *credential =nil; 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; //后端給過(guò)來(lái)的pfx證書導(dǎo)入鑰匙串,然后導(dǎo)出為.p12文件,名字隨意。示例為:client.p12 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 voidcerts[] = {certificate}; CFArrayRef certArray =CFArrayCreate(kCFAllocatorDefault, certs,1,NULL); credential =[NSURLCredential credentialWithIdentity:identity certificates:(__bridge NSArray)certArray persistence:NSURLCredentialPersistencePermanent]; disposition =NSURLSessionAuthChallengeUseCredential; } } } _credential = credential; return disposition; }];}+(BOOL)extractIdentity:(SecIdentityRef)outIdentity andTrust:(SecTrustRef )outTrust fromPKCS12Data:(NSData )inPKCS12Data { OSStatus securityError = errSecSuccess; //client certificate password NSDictionaryoptionsDictionary = [NSDictionary dictionaryWithObject:@"p12證書密碼" 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 voidtempIdentity =NULL; tempIdentity= CFDictionaryGetValue (myIdentityAndTrust,kSecImportItemIdentity); outIdentity = (SecIdentityRef)tempIdentity; const voidtempTrust =NULL; tempTrust = CFDictionaryGetValue(myIdentityAndTrust,kSecImportItemTrust); outTrust = (SecTrustRef)tempTrust; } else { NSLog(@"Failedwith error code %d",(int)securityError); return NO; } return YES;}+ (AFSecurityPolicy)getSecurityPolicy{ NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"cer證書名字" ofType:@"cer"]; NSData *certData = [NSData dataWithContentsOfFile:cerPath]; NSSet *certSet = [NSSet setWithObject:certData]; AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate]; policy.allowInvalidCertificates = YES; policy.validatesDomainName = NO; policy.pinnedCertificates = certSet; /**** SSL Pinning ****/ return policy;}
最近在配置https,使用的是AFNetWorking3.0。
一直報(bào)個(gè)NSArray object nil 閃退,開(kāi)始找了項(xiàng)目本身的問(wèn)題,一直找不到。
后來(lái)發(fā)現(xiàn),是AFNetWorking里AFSecurityPolicy.m文件中的方法
(BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain,代碼片段里
解決方法:
1.將后端發(fā)過(guò)來(lái)的.crt證書,修改后綴.cer,導(dǎo)入鑰匙串
2.再?gòu)蔫€匙串導(dǎo)出該證書,拉到項(xiàng)目里直接使用