项目中用到了HTTPDNS,顺便把做的过程和遇到的流程记录下。
<h1>1、为啥要做HttpDNS?
<h6>对于互联网,域名是访问的第一跳,而这一跳很多时候会“失足”,导致访问错误内容,失败连接等。
HttpDNS是使用HTTP协议向DNS服务器的80端口进行请求,代替传统的DNS协议向DNS服务器的53端口进行请求,绕开了运营商的Local DNS,从而避免了使用运营商Local DNS造成的劫持和跨网问题。具体可以看看鹅厂的这篇文章(<a href="http://mp.weixin.qq.com/s?__biz=MzA3ODgyNzcwMw==&mid=201837080&idx=1&sn=b2a152b84df1c7dbd294ea66037cf262&scene=2&from=timeline&isappinstalled=0&utm_source=tuicool"> 鹅厂DNS分析 </a>).
<h1>2、怎么做的?
<h6>我这边选用的腾讯云的移动解析HttpDNS,接入SDK,<a href="https://www.qcloud.com/document/product/379/6469">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.jianshu.com/p/7c89b8c5482a"> NSURLProtocol 科普</a>。
<h1>3、遇到的问题
<h6>在前面两步做的都比较顺利,在把域名替换成ip访问网络的时候出现的问题:“返回此服务器的证书无效。您可能正在连接到一个伪装成“14.215.177.37”的服务器,这会威胁到您的机密信息的安全(14.215.177.37 是www.baidu.com的ip)。”
后来自信看了sdk文档,发现在Https建立连接的时候是需要验证证书的,<a href="https://www.qcloud.com/document/product/379/6471#ios.E9.83.A8.E5.88.86.E4.BB.A3.E7.A0.81"> 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 href="http://www.cnblogs.com/machao/p/5704201.html"> Https建立连接过程</a>