1.設置代理
NSURLSession *sesson = [NSURLSession sessionWithConfiguration:
[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc]init]];
2.在代理方法中實現對證書的操作
方法一:這是在開發(fā)者足夠信任后端的安全的情況下做的紊遵,比如調個接口账千,這樣做的結果就是忽略證書的驗證威恼,直接信任坤检。
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{
if([challenge.protectionSpace.authenticationMethodisEqualToString:NSURLAuthenticationMethodServerTrust]){//服務器信任證書
NSURLCredential *credential = [NSURLCredentialcredentialForTrust:challenge.protectionSpace.serverTrust];//服務器信任證書
if(completionHandler)
completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
}
}
方法二:可以把證書加到工程中,然后https訪問時在代理方法中進行證書的驗證
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:
(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{
SecTrustRef servertrust = challenge.protectionSpace.serverTrust;
SecCertificateRef certi= SecTrustGetCertificateAtIndex(servertrust, 0);
NSData *certidata = CFBridgingRelease(CFBridgingRetain(CFBridgingRelease(SecCertificateCopyData(certi))));
NSString *path = [[NSBundle mainBundle] pathForResource:@"https" ofType:@"cer"];
NSData *localCertiData = [NSData dataWithContentsOfFile:path];
if ([certidata isEqualToData:localCertiData]) {
NSURLCredential *credential = [[NSURLCredential alloc] initWithTrust:servertrust];
[challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
NSLog(@"服務端證書認證通過");
}else {
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
NSLog(@"服務端認證失敗");
}
}
-(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]) {
if (self.sslChallengeMode == XKHTTPClientSSLChallengeModeNone) {
// 使用服務端的證書對服務端進行校驗,那肯定是怎樣都通過,自簽名證書都能通過
disposition = NSURLSessionAuthChallengeUseCredential;
credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
} else if(self.sslChallengeMode == XKHTTPClientSSLChallengeModeSimple) {
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
NSArray * policies = @[ (__bridge_transfer id)SecPolicyCreateBasicX509() ];
SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies);
SecTrustResultType result;
if(SecTrustEvaluate(serverTrust, &result) == errSecSuccess &&
(result == kSecTrustResultUnspecified || result == kSecTrustResultProceed)) {
// x509認證,不會對服務端證書中的域名和請求的域名進行一致性校驗
// 校驗成功,則直接傳遞服務端證書來對服務端鑒權進行校驗,即:怎樣都會成功
disposition = NSURLSessionAuthChallengeUseCredential;
credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
} else {
// x509校驗失敗,則走默認的校驗邏輯
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
} else {
// 默認校驗邏輯:ATS,即對證書錨點删铃、證書鏈進行校驗且會對證書中的域名和請求的域名的一致性進行校驗
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
} else {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
if (completionHandler) {
completionHandler(disposition, credential);
}
}
在了解了網絡請求的流程之后桦山,我們可以先測試一下自己項目網絡請求耗時分布攒射。
通過監(jiān)聽NSURLSession的didFinishCollectingMetrics回調方法,了解各種耗時操作
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0))
{
if (@available(iOS 10.0, *)) {
for (NSURLSessionTaskTransactionMetrics *sessionMetric in metrics.transactionMetrics) {
NSInteger dom = ([sessionMetric.domainLookupEndDate timeIntervalSince1970] - [sessionMetric.domainLookupStartDate timeIntervalSince1970]) * 1000 ;
NSInteger sec = ([sessionMetric.secureConnectionEndDate timeIntervalSince1970] - [sessionMetric.secureConnectionStartDate timeIntervalSince1970]) * 1000;
NSInteger con = ([sessionMetric.connectEndDate timeIntervalSince1970] - [sessionMetric.connectStartDate timeIntervalSince1970]) * 1000;
NSInteger req = ([sessionMetric.requestEndDate timeIntervalSince1970] - [sessionMetric.requestStartDate timeIntervalSince1970]) * 1000;
NSInteger res = ([sessionMetric.responseEndDate timeIntervalSince1970] - [sessionMetric.responseStartDate timeIntervalSince1970]) * 1000;
NSInteger tot = ([sessionMetric.responseEndDate timeIntervalSince1970] - [sessionMetric.fetchStartDate timeIntervalSince1970]) * 1000;
NSString *locip = @"";
NSString *remip = @"";
if (@available(iOS 13.0, *)) {
locip = [NSString stringWithFormat:@"%@", sessionMetric.localAddress];
remip = [NSString stringWithFormat:@"%@", sessionMetric.remoteAddress];
}
NSLog(@"metric path:%@ 總耗時:%ldms, 域名解析:%ldms, 連接耗時:%ldms(包括TLS:%ldms), 請求:%ldms, 回調:%ldms l:%@ r:%@",sessionMetric.request.URL.lastPathComponent,tot,dom,con,sec,req,res, locip, remip);
}
}
}
此時就可以進行對應的網絡情況優(yōu)化恒水。