httpdns实战感受(ios开发篇章)

近期项目中为了解决域名问题在项目中集成了阿里云的第三方域名解析服务HttpDns,现在描述一下我的实战感受

首先提出几个问题,本文就围绕着这几个问题来进行编辑。

1. 为什么要集成HttpDns?

2. 集成HttpDns的步骤?

3. 集成过程中容易遇到哪些问题?

第一个问题:

客户端进行网络请求,首先会经过运营商(移动,联通,电信)的Local DNS。因为我们进行网络的路径通常都是使用域名的拼接的,所以需要经过运营商根据域名找到对应的ip,然后再访问到公司服务器。而经过运营商的Local Dns的时候,有可能存在劫持的情况,导致访问的结果并不是我们想要的。或者在我们访问的网页上打入一些广告之类的。为了解决类似情况,我们在进行网络请求之前需要对域名进行解析,解析的结果是对应的ip地址。那么发送网络请求的时候,运营商发现你的路径是ip,就会直接"放行"。这样可以防止域名劫持,间接的也提高了访问的速度,因为我们中间跳过了运营商这一步。那么怎样对域名进行解析呢?这就涉及到第三方服务了。阿里云,腾讯都有域名解析的第三方服务,毕竟他们的技术比较成熟。我们公司集成的是阿里云的HttpDns。

第二个问题:

集成HttpDns步骤(其实文档上也有)

第一步:需要到登陆阿里云账号(没有的注册),然后找到HttpDns,并且开通。开通之后,就能获取到一个AccountId,这个AccountId在项目中需要使用。然后再添加你项目中需要解析的域名,控制台就可以看到每天域名解析的次数(当天解析的要到第二天才能看到)。

第二步:添加包含HttpDns解析功能的frameWork,并添加相应的依赖库。然后照着文档在appDelegate中添加相应代码(设置AccountId,设置降级代理,预解析域名...),这个文档上都写的比较清楚。接下来就涉及到域名解析了,解析分两种情况:http、https请求。 但是不管是http还是https请求都有一些共同步骤,首先将域名成ip,由于通常情况下都使用异步解析,所以有可能不能立即拿到解析后的ip(httpdns有缓存机制,首先查看缓存,缓存没有返回nil,然后异步解析域名,解析成功之后更新缓存),所以我在程序启动的时候就手动调用了异步解析的接口,解析项目需要使用到的域名。那么在做网络请求之前再解析的时候就能获取到解析之后的iP了。然后将请求路径中的域名替换成ip。将域名替换成ip之后直接进行网络请求,会导致网络请求不通过,原因是因为在我们将网络请求中的域名替换成ip后,网络请求中的head中host字段也会更换成ip,因为一台服务器我们会有很多接口服务同时存在,服务器接收到请求后无法根据域名去判断我们访问的是哪个服务。所以就会导致网络请求不通过。所以我们在将域名替换成ip之后需要将请求头(header)中的host字段设置回域名。做完这些操作之后,http请求就能正常解析,能够正常访问了。但是https请求光做这些还不够,由于https要做证书校验,所以针对https请求还需要绑定证书策略,将ip重新替换成域名在执行证书校验。以NSURLSession进行的网络请求为例:代码如下

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px "PingFang SC"; color: #008f00 }
p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #008f00 }
p.p4 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #3495af }
p.p5 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #0433ff }
span.s1 { }
span.s2 { color: #0433ff }
span.s3 { color: #3495af }
span.s4 { color: #008f00 }
span.s5 { font: 18.0px Menlo }
span.s6 { color: #000000 }
span.s7 { font: 18.0px "PingFang SC" }
span.s8 { font: 18.0px "PingFang SC"; color: #008f00 }
span.s9 { font: 18.0px Menlo; color: #0433ff }

- (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);

}

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #0433ff }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo }
p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #3495af }
p.p4 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px "PingFang SC"; color: #008f00 }
p.p5 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #008f00 }
span.s1 { }
span.s2 { color: #0433ff }
span.s3 { color: #3495af }
span.s4 { color: #000000 }
span.s5 { color: #008f00 }
span.s6 { font: 18.0px Menlo }
span.s7 { color: #b4261a }
span.s8 { font: 18.0px "PingFang SC" }

#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 = [[self.request allHTTPHeaderFields] objectForKey:@"host"];

if (!host) {

host = self.request.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);

}

https请求加上这些代码之后,也就能通过证书校验了,就能正常访问了。

第三个问题:

容易踩的两个坑就是 1. 将域名替换成ip之后,没有将header中的host字段设置成域名 2. https请求没有重新将ip替换成域名之后在做证书校验

在我们的项目中,我遇到的两个问题

1. 我们项目中使用的是公共的网络请求工具类,然后使用的域名确不止一个,所以就导致当从一个域名的网络请求切换到另一个域名的网络请求的时候,网络请求不通过,这是因为header中的   host字段使用的还是上一个域名,导致header中的host字段与真正请求的ip不匹配

解决办法:在每一个网络请求之前都根据当前网络请求的域名解析ip,将ip替换成域名,并且每一个请求都将header中的host字段设置成当前域名。不做统一设置(如果项目中使用的域名只有   一个则可以统一设置)

2. 我们公司解析出来的ip在某些地区受运营商的限制,网络请求无法通过。在相同的网络状态下,不管是使用运营商的Local DNS还是使用第三方的HttpDns,解析的都是同一个域名,所以即   使使用了HttpDns解析,我们的项目在受限制的地区任然无法访问公司服务

解决办法:后台增加域名,当网络请求失败之后,进行域名切换,这样就能解决在受限地区无法访问的问题

总而言之,集成HttpDns有很多好处。1. 防止域名劫持 2. 优化网络,提高网络请求的访问速度

时间: 2024-10-25 14:51:59

httpdns实战感受(ios开发篇章)的相关文章

搞了一段时间iOS开发的感受

接触iOS有了一小段的时间了,属于半路出家,之前只是对C和数据结构有一些了解并不深入,Objective-C算是第一门较为深入的了解吧,知道自己在各个方面都差的很远,需要学习的东西很多很多. 第一个阶段就是基础的学习,熟悉UIFoundation和UIKit的基础框架,能自己写些简单的app,花了几个月的时间.掌握了这部分的基础知识后,开始在公司做项目,开始看写app发现自己好多实现都无从下手,当然还有很多看不到的地方,于是就开始看一些code4app和github上的代码,先看example,

iOS开发——使用技术OC篇&项目实战总结之开发技巧

项目实战总结之开发技巧 本文收集了25个关于可以提升程序性能的提示和技巧 1.使用ARC进行内存管理 2.在适当的情况下使用reuseIdentifier 3.尽可能将View设置为不透明(Opaque) 4.避免臃肿的XIBs 5.不要阻塞主线程 6.让图片的大小跟UIImageView一样 7.选择正确的集合 8.使用GZIP压缩 9.重用和延迟加载View 10.缓存.缓存.缓存 11.考虑绘制 12.处理内存警告 13.重用花销很大的对象 14.使用Sprite Sheets 15.避免

iOS开发——完整项目实战OC篇&百思不得姐第四天

iOS开发——完整项目实战OC篇&百思不得姐第四天 上午 一:自定义按钮使用九宫格布局 二:控件不能点击 三:获取用户点击了那个按钮 四:调整按钮内部控件的位置:主流->上下 五:不能直接使用self.navigationController中或者View中获取导航控制器 方法一: 方法二: 六:布局取整 1 // 总行数 2 3 // NSUInteger rows = sqaures.count / maxCols; 4 5 // if (sqaures.count % maxCols)

iOS开发实战——CollectionView中cell的间距设置

我在前面多篇博客中详细讲解了CollectionView的使用与自定义CollectionViewCell的设计,可以参考<iOS开发实战--CollectionView点击事件与键盘隐藏结合案例><iOS高级开发--CollectionView修改cell的文本及模型重构>这几篇博客.但是今天还是需要来讲讲CollectionView实现中的一个小小的坑,这是我最近在网上浏览时发现很多开发者经常犯的错,所以我觉得有必要来好好谈一谈. 一个CollectionView控件中,两个c

iOS开发——高级技术精选OC篇&amp;Runtime之字典转模型实战

Runtime之字典转模型实战 如果您还不知道什么是runtime,那么请先看看这几篇文章: http://www.cnblogs.com/iCocos/p/4734687.html http://www.cnblogs.com/iCocos/p/4676679.html http://www.cnblogs.com/iCocos/p/4725527.html 关于runtime的详细介绍及其相关的小实例 好了,这里就不多废话了,直接开干! 先来看看怎么使用Runtime给模型类赋值 iOS开发

iOS开发——实战OC篇&amp;环境搭建之Xib(玩转UINavigationController与UITabBarController)

iOS开发——实战OC篇&环境搭建之Xib(玩转UINavigationController与UITabBarController) 前面我们介绍了StoryBoard这个新技术,和纯技术编程的代码创建界面,本篇我们将介绍一个老的技术,但是在很多的公司或者库里面还是使用这个技术,既然如此它肯定有他的好处,至于好处这里我就不一一介绍了.在Xcode5之前是只能使用Xib或者代码的,而代码又对于很多初学者来说算是一个难题.毕竟不知道怎么下手.所以我就总结了一下这段时间自己编写程序的一个实例来说明怎么

iOS开发——实战OC篇&amp;环境搭建之纯代码(玩转UINavigationController与UITabBarController)

iOS开发——实战OC篇&环境搭建之纯代码(玩转UINavigationController与UITabBarController) 这里我们就直接上实例: 一:新建一个项目singleView Controller,命名未iCocos 二:由于我们使用的纯代码实现的,所以删除其中的StoryBoard和Viewtroller的两个文件 三:新建一个继承自TabBar Controller的类,我们命名问iCocos ViewController 三:在Appdelegate的实现文件中导入刚刚

iOS开发——开发实战篇&amp;版本控制SVN和Git简单实战总结

版本控制SVN和Git简单实战总结 如果你对iOS开发中的版本控制还不了解那么你可以先看看这篇(大致看一遍就ok) 关于版本控制使用起来并不难,但是可能你会遇到这样问题! 学了这么多命令,感觉自己都知道,而且基本上都能敲出一二,但是就是不轻松公司实际开发中到底要怎么用,或者我该怎么下手,下面我们就来看看我们到了公司之后首先要做的,和之后经常要做的一些事情(命令太多没必要去记,常用的也就那么几个). 首先,你必须先知道,在天朝,SVN目前任是主流,但是又不的不会(这里具体原因我就不多说了)! 好了

iOS开发实战——CollectionView点击事件与键盘隐藏结合案例(二)

我在前一篇博客中<iOS开发实战--CollectionView点击事件与键盘隐藏结合案例>详细实现了CollectionView与键盘组合操作中出现的多种情况,并解决了交互体验上的一些问题.在实际项目中也的确可以采用这种方法来操作.但是问题来了,原来的界面我们是使用UIView来操作的,也就是界面是不可滚动的.然而更为常见的场景是一个ScrollView,界面可以进行上下滚动.所以,这篇博客主要是对前一个案例进行优化.还有一个问题是,在自动布局Masonry结合ScrollView中,会碰到