項目中用到了HTTPDNS,順便把做的過程和遇到的流程記錄下。
<h1>1、為啥要做HttpDNS?
<h6>對于互聯網,域名是訪問的第一跳,而這一跳很多時候會“失足”,導致訪問錯誤內容,失敗連接等。
HttpDNS是使用HTTP協議向DNS服務器的80端口進行請求,代替傳統的DNS協議向DNS服務器的53端口進行請求,繞開了運營商的Local DNS,從而避免了使用運營商Local DNS造成的劫持和跨網問題。具體可以看看鵝廠的這篇文章(<a > 鵝廠DNS分析 </a>).
<h1>2、怎么做的?
<h6>我這邊選用的騰訊云的移動解析HttpDNS,接入SDK,<a >SDK鏈接</a>。注意在配置的時候要在info.plist配置Demo中給出的信息,等公司申請下來賬號以后替換對應的key和id。
/**
域名解析ip
@param host 域名
@return ip(優先使用ipv6),沒解析到返回host
*/
- (NSString *)dnsByDomain:(NSString *)domain {
NSTimeInterval time1 = [[NSDate date] timeIntervalSince1970];
NSArray *result = [[MSDKDns sharedInstance] WGGetHostByName:domain];
NSTimeInterval time2 = [[NSDate date] timeIntervalSince1970];
NSLog(@"HttpDNS 本次耗時:%f", (time2 - time1) * 1000);
if (result && result.count > 1) {
NSString *ipv4 = result[0];
NSString *ipv6 = result[1];
if (ipv6 && ipv6.length > 1) {
NSLog(@"HttpDNS domain(%@),ip(%@)", domain, ipv6);
return [NSString stringWithFormat:@"%@", ipv6];
} else if (ipv4 && ipv4.length > 1) {
NSLog(@"HttpDNS domain(%@),ip(%@)", domain, ipv4);
return [NSString stringWithFormat:@"%@", ipv4];
}
}
return nil;
}
<h4>其中比較重要的是如何攔截網絡請求,把其中的域名換成對應的ip地址。
<h6>我在項目中,選用的是自定義NSURLProtocol的方法,對于不了解的同學可以在這個地方科普下<a href="http://www.lxweimin.com/p/7c89b8c5482a"> NSURLProtocol 科普</a>。
<h1>3、遇到的問題
<h6>在前面兩步做的都比較順利,在把域名替換成ip訪問網絡的時候出現的問題:“返回此服務器的證書無效。您可能正在連接到一個偽裝成“14.215.177.37”的服務器,這會威脅到您的機密信息的安全(14.215.177.37 是www.baidu.com的ip)。”
后來自信看了sdk文檔,發現在Https建立連接的時候是需要驗證證書的,<a > Https場景處理</a>。
但是按照文檔方法寫了后還是不能訪問,
/*
* 評估當前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);
后來看了返回的錯誤信息,發現加上result == kSecTrustResultRecoverableTrustFailure就可以正常處理了。
<h5>關于證書信任
<h6>用戶是否是自己主動設置信任的,比如有些彈窗,用戶點擊了信任
1.用戶自定義的,成功是 kSecTrustResultProceed 失敗是kSecTrustResultDeny
2.非用戶定義的, 成功是kSecTrustResultUnspecified 失敗是kSecTrustResultRecoverableTrustFailure
這個感覺是服務器的問題,還沒有確定問題原因。
<a > Https建立連接過程</a>