全部产品
存储与CDN 数据库 安全 应用服务 数加·人工智能 数加·大数据基础服务 互联网中间件 视频服务 阿里云办公 培训与认证 物联网
HTTPDNS

iOS SDK手册

更新时间:2017-09-06 18:59:56

1. 前言

本文档介绍了HTTPDNS iOS SDK的使用方式。

HTTPDNS是阿里云面向移动开发者提供的移动端DNS解析服务。通过该SDK,开发者可以在自己的iOS APP中获得可靠、实时、精准的DNS解析服务,彻底解决传统DNS面临的域名劫持、解析时延长、调度不精准等问题。

您可以通过获取alicloud-ios-demo工程源码获得HTTPDNS服务的使用例程。

1.1 手动集成SDK

  • 您可以通过上述 GitHub demo获取 HTTPDNS SDK
  • 您可以通过访问移动服务APP列表页(https://ams.console.aliyun.com/#/download 若您第一次访问,请创建 APP),勾选下图红框中的 HTTPDNS 组件获取 SDK。

ams

1.2 Pod集成

  • 指定Master仓库和阿里云仓库:
  1. source 'https://github.com/CocoaPods/Specs.git'
  2. source 'https://github.com/aliyun/aliyun-specs.git'
  • 添加依赖:
  1. pod 'AlicloudHTTPDNS', '~> 1.5.2'

(~>为模糊指定版本号方式,~> 1.5.2表明引用版本位于1.5.2 <= version < 1.6.0之间的最新版本SDK,用户可参考Podfile Syntax Reference,根据项目需要指定SDK版本。)

1.3 修改编译选项

Target->Linking->Other Linker Flags中添加 -ObjC 选项。

不知道如何修改编译选项?请参考:

如何修改编译选项

注意:请注意 -ObjC 的大小写。


2. 应用程序配置与初始化

HTTPDNS iOS SDK,自v1.1.0版本已全面支持苹果ATS要求,无需在Info.plist中配置ATS。

2.1 依赖

系统公共库:

  • libresolv.tbd
  • CoreTelephony.framework
  • SystemConfiguration.framework

AMS组件包

  • UTDID.framework
  • AlicloudUtils.framework

如果遇到 UTDID 冲突可参考:《阿里云-移动云产品SDK UTDID冲突解决方案》

2.2 获取服务实例

HTTPDNS iOS SDK以全局service实例的方式提供域名解析服务,您可以通过以下方式获取实例:

  1. // 设置AccoutID,当您开通HTTPDNS服务时,您可以在控制台获取到您对应的Accout ID信息
  2. HttpDnsService *httpdns = [[HttpDnsService alloc] initWithAccountID::*****];

2.3 设置预解析域名

在您初始化程序时,可以选择性地预先向HTTPDNS SDK中注册您后续可能会使用到的域名,以便SDK提前解析,减少后续解析域名时请求的时延。您只需调用以下接口:

  1. NSArray * hosts = [[NSArray alloc] initWithObjects:@"www.taobao.com", @"www.aliyun.com", nil];
  2. [httpdns setPreResolveHosts:hosts];

注意预解析接口设置的同时会实时触发异步网络请求,应该在代码逻辑上确保调用预解析接口时,已经进行了必备的初始化设置。

比如:setHTTPSRequestEnabled: 需要在预解析接口之前调用,否则会导致预解析的相关 IP 采用 HTTP请求。

2.4 启用鉴权功能

首先需要在控制台开启鉴权功能:

open auth feature

在控制台开启鉴权功能后,SDK 需要更改初始化方式,改用下面的方法进行初始化,即可开启鉴权:

  1. /*!
  2. * @brief 启用鉴权功能的初始化接口
  3. * @details 初始化、开启鉴权功能,并设置 HTTPDNS 服务 Account ID,鉴权功能对应的 secretKey。
  4. * 您可以从控制台获取您的 Account ID 、secretKey 信息。
  5. * 此方法会初始化为单例。
  6. * @param accountId 您的 HTTPDNS Account ID
  7. * @param secretKey 鉴权对应的 secretKey
  8. */
  9. - (instancetype)initWithAccountID:(int)accountID secretKey:(NSString *)secretKey;

目前 iOS SDK 鉴权时间戳过期时间统一为 10 分钟,鉴权机制细节可以参考《HTTPDNS > 开发指南 > HTTP API手册 > 鉴权解析接口》

同时鉴权功能,支持对设备的时间进行校对,对应的方法为:

  1. /*!
  2. * @brief 校正 App 签名时间
  3. * @param authCurrentTime 用于校正的时间戳,正整数。
  4. * @details 不进行该操作,将以设备时间为准,为`(NSUInteger)[[NSDate date] timeIntervalSince1970]`。进行该操作后,如果有偏差,每次网络请求都会对设备时间进行矫正。
  5. * @attention 校正操作在 APP 的一个生命周期内生效,APP 重启后需要重新设置才能重新生效。可以重复设置。
  6. */
  7. - (void)setAuthCurrentTime:(NSUInteger)authCurrentTime;

3. 服务API与使用示例

3.1 服务API

  1. /**
  2. * 初始化并设置 HTTPDNS 服务 Account ID,您可以从控制台获取您的 Account ID 信息
  3. * 此方法会初始化为单例。
  4. * @param accountId 您的 HTTPDNS Account ID
  5. */
  6. - (instancetype)initWithAccountID:(int)accountID;
  7. /*!
  8. * @brief 启用鉴权功能的初始化接口
  9. * @details 初始化、开启鉴权功能,并设置 HTTPDNS 服务 Account ID,鉴权功能对应的 secretKey。
  10. * 您可以从控制台获取您的 Account ID 、secretKey 信息。
  11. * 此方法会初始化为单例。
  12. * @param accountId 您的 HTTPDNS Account ID
  13. * @param secretKey 鉴权对应的 secretKey
  14. */
  15. - (instancetype)initWithAccountID:(int)accountID secretKey:(NSString *)secretKey;
  16. /*!
  17. * @brief 校正 App 签名时间
  18. * @param authCurrentTime 用于校正的时间戳,正整数。
  19. * @details 不进行该操作,将以设备时间为准,为`(NSUInteger)[[NSDate date] timeIntervalSince1970]`。进行该操作后,如果有偏差,每次网络请求都会对设备时间进行矫正。
  20. * @attention 校正操作在 APP 的一个生命周期内生效,APP 重启后需要重新设置才能重新生效。可以重复设置。
  21. */
  22. - (void)setAuthCurrentTime:(NSUInteger)authCurrentTime;
  23. /**
  24. * 获取HTTPDNS服务实例
  25. */
  26. + (instancetype)sharedInstance;
  27. /**
  28. * 设置HTTPDNS域名解析请求类型(HTTP/HTTPS),若不调用该接口,默认为HTTP请求。
  29. * HTTP请求基于底层CFNetwork实现,不受ATS限制;
  30. *
  31. * @param enable YES: HTTPS请求, NO: HTTP请求
  32. */
  33. - (void)setHTTPSRequestEnabled:(BOOL)enable;
  34. /**
  35. * 将app使用到的域名预设进来,以便于HTTPDNS 进行预解析
  36. *
  37. * @param hosts 预解析列表
  38. */
  39. - (void)setPreResolveHosts:(NSArray *)hosts;
  40. /**
  41. * 异步解析接口,首先查询缓存,若存在则返回结果,若不存在返回nil并且进行异步域名解析更新缓存
  42. *
  43. * @param host 域名(如www.aliyun.com)
  44. * @return 域名对应的解析结果
  45. */
  46. - (NSString *)getIpByHostAsync:(NSString *)host;
  47. /**
  48. * 异步解析接口,首先查询缓存,若存在则返回结果列表,若不存在返回nil并且进行异步域名解析更新缓存
  49. *
  50. * @param host 域名(如www.aliyun.com)
  51. * @return 域名对应的解析结果列表
  52. */
  53. - (NSArray *)getIpsByHostAsync:(NSString *)host;
  54. /**
  55. * 异步解析接口,首先查询缓存,若存在则返回结果,若不存在返回空对象并且进行异步域名解析更新缓存。返回的结果是URL使用场景下的格式化结果
  56. *
  57. * @param host 域名(如www.aliyun.com)
  58. * @return 域名对应的解析结果
  59. */
  60. - (NSString *)getIpByHostAsyncInURLFormat:(NSString *)host;
  61. /**
  62. * 设置降级策略,用户可定制规则降级为原生DNS解析方式;
  63. *
  64. * @param delegate 降级代理
  65. */
  66. - (void)setDelegateForDegradationFilter:(id<HttpDNSDegradationDelegate>)delegate;
  67. @protocol HttpDNSDegradationDelegate <NSObject>
  68. /**
  69. * 降级过滤器
  70. *
  71. * @param hostName 当前的目标域名(如www.aliyun.com),您可以针对域名进行降级过滤
  72. * @return 是否降级走原生DNS逻辑
  73. */
  74. - (BOOL)shouldDegradeHTTPDNS:(NSString *)hostName;
  75. @end
  76. /**
  77. * 是否允许HTTPDNS返回TTL过期的域名
  78. * 当您允许返回TTL过期的IP时,SDK在实时返回过期IP的同时依然会进行异步更新以获取最新的IP信息
  79. *
  80. * @param enable 是否返回TTL过期域名
  81. */
  82. - (void)setExpiredIPEnabled:(BOOL)enable;
  83. /**
  84. * 本地日志 log 开关
  85. */
  86. - (void)setLogEnabled:(BOOL)enable;
  87. /**
  88. * 设置网络切换时是否自动刷新所有域名解析结果,如果打开此开关,在网络切换时,会自动刷新所有域名的解析结果,但会产生一定流量消耗
  89. *
  90. * @param enable
  91. */
  92. - (void)setPreResolveAfterNetworkChanged:(BOOL)enable;
  93. /*!
  94. * 设置网络请求的超时时间
  95. * 超时时间默认为15秒
  96. * @param timeoutInterval 超时时间,单位为秒
  97. */
  98. - (void)setTimeoutInterval:(NSTimeInterval)timeoutInterval;
从安全角度我们强烈建议用户使用异步解析接口。在DDOS攻击等特殊场景下,HTTPDNS有可能会触发流量黑洞,此时同步接口就有可能出现短暂的请求解析超时等待,而异步接口的网络请求都是后台操作的,业务层面不会感知到请求超时的动作,能够做到对异常情况的冗余。
  1. /**
  2. * 同步解析接口,首先查询缓存,若存在则返回结果,若不存在则进行同步域名解析请求,解析完成返回最新解析结果,若解析失败返回nil
  3. *
  4. * @param host 域名(如www.aliyun.com)
  5. * @return 域名对应的解析结果
  6. */
  7. - (NSString *)getIpByHost:(NSString *)host;
  8. /**
  9. * 同步解析接口,首先查询缓存,若存在则返回结果,若不存在则进行同步域名解析请求,解析完成返回最新解析结果列表,若解析失败返回nil
  10. *
  11. * @param host 域名(如www.aliyun.com)
  12. * @return 域名对应的解析结果列表
  13. */
  14. - (NSArray *)getIpsByHost:(NSString *)host;
  15. /**
  16. * 同步解析接口,首先查询缓存,若存在则返回结果,若不存在则进行同步域名解析请求,解析完成返回最新解析结果,若解析失败返回空对象。返回的结果是URL使用场景下的格式化结果
  17. *
  18. * @param host 域名(如www.aliyun.com)
  19. * @return 域名对应的解析结果
  20. */
  21. - (NSString *)getIpByHostInURLFormat:(NSString *)host;

HTTPDNS 场景下兼容 IPv6-only 网络环境需要注意的细节:

当您使用 IP 形式的 URL 进行网络请求时,IPv4 与 IPv6 的 IP 地址使用方式略有不同:

即在URL中使用IPv6地址时需要在IPv6地址基础上额外加上[]。为了方便开发者的使用,HTTPDNS提供了适配URL格式的IP获取接口 -[HttpDnsService getIpByHostAsyncInURLFormat:]。当您通过HTTPDNS进行IP获取,并使用该IP进行基于URL的网络访问时,您可以通过上述API直接获取符合URL使用场景,格式化后的IP信息,如1.1.1.1[2001:db8:c000:221::]。如果您仅仅为了获取精准的IP信息并另做它用,您可以继续使用老接口 -[HttpDnsService getIpByHostAsync:]

3.2 使用示例

您可以通过获取alicloud-ios-demo工程源码获得HTTPDNS服务的使用例程。

4. 注意事项

4.1 HTTP请求头HOST字段设置

标准的HTTP协议中服务端会将HTTP请求头HOST字段的值作为请求的域名信息进行解析。使用HTTPDNS后,您可能需要将HTTP请求URL中的HOST字段替换为HTTPDNS解析获得的IP,这时标准的网络库会将您的IP赋值给HTTP请求头的HOST字段,进而导致服务端的解析异常(服务端认可的是您的域名信息,而非IP信息)。为了解决这个问题,您可以主动设置HTTP请求HOST字段的值,如:

  1. NSString *originalUrl = @"http://www.aliyun.com/";
  2. NSURL* url = [NSURL URLWithString:originalUrl];
  3. NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:url];
  4. // 同步接口获取IP
  5. NSString* ip = [httpdns getIpByHostAsync:url.host];
  6. if (ip) {
  7. // 通过HTTPDNS获取IP成功,进行URL替换和HOST头设置
  8. NSRange hostFirstRange = [originalUrl rangeOfString: url.host];
  9. if (NSNotFound != hostFirstRange.location) {
  10. NSString* newUrl = [originalUrl stringByReplacingCharactersInRange:hostFirstRange withString:ip];
  11. request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:newUrl]];
  12. // 设置请求HOST字段
  13. [request setValue:url.host forHTTPHeaderField:@"host"];
  14. }
  15. }

部分网络库支持COOKIE的自动存储管理,当您使用HTTPDNS进行IP URL请求时,部分网络库会将您URL中的IP信息作为COOKIE对应的域名信息进行存储管理(而非HTTP请求头HOST字段信息),进而造成COOKIE管理与使用上的困扰,因此您需要关闭COOKIE的自动管理功能(默认关闭)。

4.3 HTTPS/WebView/SNI场景

4.4 代理情况下的使用

当存在中间HTTP代理时,客户端发起的请求中请求行会使用绝对路径的URL,在您开启HTTPDNS并采用IP URL进行访问时,中间代理将识别您的IP信息并将其作为真实访问的HOST信息传递给目标服务器,这时目标服务器将无法处理这类无真实HOST信息的HTTP请求。移动网关提供了X-Online-Host的私有协议字段来解决这个问题,比如:

  1. 目标URLhttp://www.aliyun.com/product/oss/
  2. 通过HTTPDNS解析出来的www.aliyun.comIP1.1.1.1
  3. 代理:10.0.0.172:80
  4. 您的HTTP请求头:
  5. GET http://1.1.1.1/product/oss/ HTTP/1.1 # 通过代理发起的HTTP请求头,请求行是一个绝对路径
  6. Host: www.aliyun.com # 这个Header会被代理网关忽略,代理网关会使用请求行绝对路径中的host字段作为源站的host,即1.1.1.1
  7. X-Online-Host: www.aliyun.com # 这个Header就是移动网关为了传递真实Host添加的私有头部,源站需要配置识别该私有头部以获取真实的Host信息

同样您可以通过下述方法进行X-Online-Host请求头域的设置,并在服务端设置对该私有头域的解析。

  1. [request setValue:url.host forHTTPHeaderField:@"X-Online-Host"];

在绝大多数场景下,我们建议您在代理模式下关闭HTTPDNS功能。


本文导读目录