httpdns_ios_demo/httpdns_ios_demo/Example/HttpsExample/HTTPSSimpleScenario.m (105 lines of code) (raw):

// // HTTPSScene.m // httpdns_ios_demo // // Created by Miracle on 2024/7/22. // #import "HTTPSSimpleScenario.h" #import <AlicloudHttpDNS/AlicloudHttpDNS.h> @interface HTTPSSimpleScenario () <NSURLSessionTaskDelegate, NSURLSessionDataDelegate> @end @implementation HTTPSSimpleScenario - (void)httpDnsQueryWithURL:(NSString *)originalUrl completionHandler:(void(^)(NSString * message))completionHandler { // 组装提示信息 __block NSMutableString *tipsMessage = [NSMutableString string]; NSURL *url = [NSURL URLWithString:originalUrl]; NSMutableURLRequest *request; NSString *resolvedIpAddress = [self resolveAvailableIp:url.host]; NSString *requestUrl = originalUrl; if (resolvedIpAddress) { // 通过HTTPDNS获取IP成功,进行URL替换和HOST头设置 requestUrl = [originalUrl stringByReplacingOccurrencesOfString:url.host withString:resolvedIpAddress]; NSString *log = [NSString stringWithFormat:@"Resolve host(%@) by HTTPDNS successfully, result ip: %@", url.host, resolvedIpAddress]; NSLog(@"%@", log); [tipsMessage appendString:log]; } else { NSString *log = [NSString stringWithFormat:@"Resolve host(%@) by HTTPDNS failed, keep original url to request", url.host]; NSLog(@"%@", log); [tipsMessage appendString:log]; } // 设置request request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:requestUrl]]; [request setValue:url.host forHTTPHeaderField:@"host"]; // 发送网络请求 [self sendRequest:request completionHandler:^(NSString *message) { [tipsMessage appendFormat:@"\n\n %@",message]; if (completionHandler) { completionHandler(tipsMessage); } }]; } - (NSString *)resolveAvailableIp:(NSString *)host { HttpDnsService *httpDnsService = [HttpDnsService sharedInstance]; HttpdnsResult *result = [httpDnsService resolveHostSyncNonBlocking:host byIpType:HttpdnsQueryIPTypeAuto]; NSLog(@"resolve host result: %@", result); if (!result) { return nil; } if (result.hasIpv4Address) { return result.firstIpv4Address; } else if (result.hasIpv6Address) { return [NSString stringWithFormat:@"[%@]", result.firstIpv6Address]; } else { return nil; } } - (void)sendRequest:(NSURLRequest *)request completionHandler:(void(^)(NSString * message))completionHandler { NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSString *errorStr = [NSString stringWithFormat:@"Http request failed with error: %@", error]; if (completionHandler) { completionHandler(errorStr); } return; } NSMutableString *message = [NSMutableString string]; NSString *responseStr = [NSString stringWithFormat:@"HttpResponse: %@", response.description]; [message appendFormat:@"\n\n%@", responseStr]; NSString *dataStr = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]; [message appendFormat:@"\n\nHttpResponseData:\n %@", dataStr]; if (completionHandler) { completionHandler(message); } NSLog(@"response data: %@", dataStr); }]; [task resume]; } - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain { // 创建证书校验策略 NSMutableArray *policies = [NSMutableArray array]; if (domain) { [policies addObject:(__bridge_transfer id) SecPolicyCreateSSL(true, (__bridge CFStringRef) domain)]; } else { [policies addObject:(__bridge_transfer id) SecPolicyCreateBasicX509()]; } // 绑定校验策略到服务端的证书上 SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef) policies); // 评估当前serverTrust是否可信任,官方建议在result = kSecTrustResultUnspecified 或 kSecTrustResultProceed的情况下serverTrust可以被验证通过,https://developer.apple.com/library/ios/technotes/tn2232/_index.html // 关于SecTrustResultType的详细信息请参考SecTrust.h SecTrustResultType result; SecTrustEvaluate(serverTrust, &result); return (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed); } #pragma mark - NSURLSessionTaskDelegate - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *_Nullable))completionHandler { if (!challenge) { return; } NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling; NSURLCredential *credential = nil; // 获取原始域名信息。 NSString *host = [[task.currentRequest allHTTPHeaderFields] objectForKey:@"host"]; if (!host) { host = task.currentRequest.URL.host; } if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { if ([self evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:host]) { disposition = NSURLSessionAuthChallengeUseCredential; credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; } else { disposition = NSURLSessionAuthChallengePerformDefaultHandling; } } else { disposition = NSURLSessionAuthChallengePerformDefaultHandling; } // 对于其他的challenges直接使用默认的验证方案 completionHandler(disposition, credential); } @end