Objective-C
Need help with httpdns-ios-sdk?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.
tencentyun

Description

智营防劫持SDK

132 Stars 34 Forks 120 Commits 8 Opened issues

Services available

Need anything else?

HTTPDNS iOS客户端接入文档(腾讯云客户专用)


本接入文档供腾讯云客户参阅

腾讯内部业务,请参阅文档HTTPDNS iOS客户端接入文档(腾讯内部业务专用).md

GitHub目录结构说明

| 目录名称 | 说明 | 适用范围 | | ------------- |-------------| -------------| | HTTPDNSDemo | iOS客户端使用HttpDns api示例Demo | 所有业务 | | HTTPDNSLibs | HTTPDNS iOS SDK目录 | 所有业务 | | HTTPDNSUnityDemo | Unity工程使用HttpDns api示例Demo | 使用Unity引擎的业务 | | HTTPDNS iOS客户端接入文档(腾讯云客户专用).docx | HTTPDNS iOS客户端接入文档(腾讯云客户专用) | 腾讯云客户 | | HTTPDNS iOS客户端接入文档(腾讯内部业务专用).docx | HTTPDNS iOS客户端接入文档(腾讯内部业务专用) | 腾讯内部业务 | | HTTPDNS iOS客户端接入文档(腾讯内部业务专用).md | HTTPDNS iOS客户端接入文档(腾讯内部业务专用) | 腾讯内部业务 | | README.md | HTTPDNS iOS客户端接入文档 | 腾讯云客户 | | VERSION.md | HTTPDNS iOS SDK历史版本修改记录 | SDK开发维护人员 |

1. 功能介绍

HttpDns的主要功能是为了有效的避免由于运营商传统LocalDns解析导致的无法访问最佳接入点的方案。原理为使用Http加密协议替代传统的DNS协议,整个过程不使用域名,大大减少劫持的可能性。

2. 安装包结构

压缩文件中包含demo工程,其中包含:

| 名称 | 适用说明 | | ------------- |-------------| | MSDKDns.framework | 适用“Build Setting->C++ Language Dialect”配置为“GNU++98”,“Build Setting->C++ Standard Library”为“libstdc++(GNU C++ standard library)”的工程。 | | MSDKDns_C11.framework | 适用于该两项配置分别为“GNU++11”“libc++(LLVM C++ standard library with C++11 support)”的工程。 |

3. SDK集成

HttpDns提供两种集成方式供iOS开发者选择: - 通过CocoaPods集成 - 手动集成

3.1 通过CocoaPods集成

在工程的Podfile里面添加以下代码:

# 适用“Build Setting->C++ Language Dialect”配置为**“GNU++98”**,“Build Setting->C++ Standard Library”为**“libstdc++(GNU C++ standard library)”**的工程。
pod 'MSDKDns'
# 适用于该两项配置分别为**“GNU++11”**和**“libc++(LLVM C++ standard library with C++11 support)”**的工程。
# pod 'MSDKDns_C11'

保存并执行

pod install
,然后用后缀为
.xcworkspace
的文件打开工程。

关于

CocoaPods
的更多信息,请查看 CocoaPods官方网站

3.2 手动集成

3.2.1 已接入灯塔(Beacon)的业务

仅需引入位于HTTPDNSLibs目录下的MSDKDns.framework(或MSDKDns_C11.framework,根据工程配置选其一)即可。

3.2.2 未接入灯塔(Beacon)的业务

灯塔(beacon)SDK是腾讯灯塔团队开发的用于移动应用统计分析的SDK, HttpDNS SDK使用灯塔(beacon)SDK收集域名解析质量数据, 辅助定位问题 - 引入依赖库(位于HTTPDNSLibs目录下): - BeaconAPIBase.framework - MSDKDns.framework(或MSDKDnsC11.framework,根据工程配置选其一) - 引入系统库: - libz.tdb - libsqlite3.tdb - libc++.tdb - Foundation.framework - CoreTelephony.framework - SystemConfiguration.framework - CoreGraphics.framework - Security.framework - 并在application:didFinishLaunchingWithOptions:加入注册灯塔代码:

    //已正常接入灯塔的业务无需关注以下代码,未接入灯塔的业务调用以下代码注册灯塔
    //******************************
    [BeaconBaseInterface setAppKey:@"0000066HQK3XNL5U"];
    [BeaconBaseInterface enableAnalytics:@"" gatewayIP:nil];
    //******************************

注意:需要在Other linker flag里加入-ObjC标志。

4. API及使用示例

4.1 设置业务基本信息

接口声明

/**
 设置业务基本信息(腾讯云业务使用)

@param appkey 业务appkey,腾讯云官网(https://console.cloud.tencent.com/httpdns)申请获得,用于上报 @param dnsid dns解析id,腾讯云官网(https://console.cloud.tencent.com/httpdns)申请获得,用于域名解析鉴权 @param dnsKey dns解析key,腾讯云官网(https://console.cloud.tencent.com/httpdns)申请获得,用于域名解析鉴权 @param debug 是否开启Debug日志,YES:开启,NO:关闭。建议联调阶段开启,正式上线前关闭 @param timeout 超时时间,单位ms,如设置0,则设置为默认值2000ms @param useHttp 是否使用http路解析,YES:使用http路解析,NO:使用https路解析,强烈建议使用http路解析,解析速度更快

@return YES:设置成功 NO:设置失败 */

  • (BOOL) WGSetDnsAppKey:(NSString *) appkey DnsID:(int)dnsid DnsKey:(NSString *)dnsKey Debug:(BOOL)debug TimeOut:(int)timeout UseHttp:(BOOL)useHttp;

示例代码

接口调用示例:

 [[MSDKDns sharedInstance] WGSetDnsAppKey: @"业务appkey,由腾讯云官网申请获得" DnsID:dns解析id DnsKey:@"dns解析key" Debug:YES TimeOut:1000 UseHttp:YES];

4.2 域名解析接口

获取IP共有两个接口,同步接口WGGetHostByName,异步接口WGGetHostByNameAsync,引入头文件,调用相应接口即可。

返回的地址格式为NSArray,固定长度为2,其中第一个值为ipv4地址,第二个值为ipv6地址。以下为返回格式的详细说明:

  • ipv4下,仅返回ipv4地址,即返回格式为:[ipv4, 0]
  • ipv6下,仅返回ipv6地址,即返回格式为:[0, ipv6]
  • 双栈网络下,返回解析到ipv4&ipv6(如果存在)地址,即返回格式为:[ipv4, ipv6]
  • 解析失败,返回[0, 0],业务重新调用WGGetHostByName接口即可。

注意:使用ipv6地址进行URL请求时,需加方框号[ ]进行处理,例如:http://[64:ff9b::b6fe:7475]/*******

使用建议:

  1. ipv6为0,直接使用ipv4地址连接
  2. ipv6地址不为0,优先使用ipv6连接,如果ipv6连接失败,再使用ipv4地址进行连接

4.2.1 同步解析接口: WGGetHostByName

接口声明
/**
 域名同步解析(通用接口)

@param domain 域名

@return 查询到的IP数组,超时(1s)或者未未查询到返回[0,0]数组 */

  • (NSArray *) WGGetHostByName:(NSString *) domain;
示例代码

接口调用示例:

NSArray *ipsArray = [[MSDKDns sharedInstance] WGGetHostByName: @"www.qq.com"];
if (ipsArray && ipsArray.count > 1) {
    NSString *ipv4 = ipsArray[0];
    NSString *ipv6 = ipsArray[1];
    if (![ipv6 isEqualToString:@"0"]) {
        //TODO 使用ipv6地址进行URL连接时,注意格式,ipv6需加方框号[]进行处理,例如:http://[64:ff9b::b6fe:7475]/
    } else if (![ipv4 isEqualToString:@"0"]){
        //使用ipv4地址进行连接
    } else {
        //异常情况返回为0,0,建议重试一次
    }
}

4.2.2 异步解析接口: WGGetHostByNameAsync

接口声明
/**
 域名异步解析(通用接口)

@param domain 域名 @param handler 返回查询到的IP数组,超时(1s)或者未未查询到返回[0,0]数组 */

  • (void) WGGetHostByNameAsync:(NSString *) domain returnIps:(void (^)(NSArray *ipsArray))handler;
示例代码

接口调用示例1:等待完整解析过程结束后,拿到结果,进行连接操作

[[MSDKDns sharedInstance] WGGetHostByNameAsync:domain returnIps:^(NSArray *ipsArray) {
    //等待完整解析过程结束后,拿到结果,进行连接操作
    if (ipsArray && ipsArray.count > 1) {
        NSString *ipv4 = ipsArray[0];
        NSString *ipv6 = ipsArray[1];
        if (![ipv6 isEqualToString:@"0"]) {
            //TODO 使用ipv6地址进行URL连接时,注意格式,ipv6需加方框号[]进行处理,例如:http://[64:ff9b::b6fe:7475]/
        } else if (![ipv4 isEqualToString:@"0"]){
            //使用ipv4地址进行连接
        } else {
            //异常情况返回为0,0,建议重试一次
        }
    }
}];

接口调用示例2:无需等待,可直接拿到缓存结果,如无缓存,则result为nil

__block NSArray* result;
[[MSDKDns sharedInstance] WGGetHostByNameAsync:domain returnIps:^(NSArray *ipsArray) {
    result = ipsArray;
}];
//无需等待,可直接拿到缓存结果,如无缓存,则result为nil
if (result) {
    //拿到缓存结果,进行连接操作
} else {
    //本次请求无缓存,业务可走原始逻辑
}

注意:业务可根据自身需求,任选一种调用方式:

示例1,优点:可保证每次请求都能拿到返回结果进行接下来的连接操作; 缺点:异步接口的处理较同步接口稍显复杂。

示例2,优点:对于解析时间有严格要求的业务,使用本示例,可无需等待,直接拿到缓存结果进行后续的连接操作,完全避免了同步接口中解析耗时可能会超过100ms的情况;缺点:第一次请求时,result一定会nil,需业务增加处理逻辑。

4.2.3 详细数据查询接口: WGGetDnsDetail

/**
详细数据查询接口

@param domain 域名

@return 查询到的详细信息 格式示例: { "v4_ips":"1.1.1.1,2.2.2.2", "v6_ips":"FF01::1,FF01::2", "v4_ttl":"100", "v6_ttl":"100", "v4_client_ip":"6.6.6.6" "v6_client_ip":"FF01::6" } */

  • (NSDictionary *) WGGetDnsDetail:(NSString *) domain;
示例代码

接口调用示例:

NSDictionary *ipsDic = [[MSDKDns sharedInstance] WGGetDnsDetail: @"www.qq.com"];
if (ipsDic && ipsDic.count > 0) {
    NSString *ipv4 = ipsDic[@"v4_ips"];
    NSString *ipv6 = ipsDic[@"v6_ips"];
    if (![ipv6 isEqualToString:@"0"]) {
        //TODO 使用ipv6地址进行URL连接时,注意格式,ipv6需加方框号[]进行处理,例如:http://[64:ff9b::b6fe:7475]/
    } else if (![ipv4 isEqualToString:@"0"]){
        //使用ipv4地址进行连接
    } else {
        //异常情况返回为0,0,建议重试一次
    }
}

5. 注意事项

  1. 如果客户端的业务是与host绑定的,比如是绑定了host的http服务或者是cdn的服务,那么在用HTTPDNS返回的IP替换掉URL中的域名以后,还需要指定下Http头的host字段。
- 以NSURLConnection为例:

    NSURL *httpDnsURL = [NSURL URLWithString:@"使用解析结果ip拼接的URL"];
    float timeOut = 设置的超时时间;
    NSMutableURLRequest *mutableReq = [NSMutableURLRequest requestWithURL:httpDnsURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval: timeOut];
    [mutableReq setValue:@"原域名" forHTTPHeaderField:@"host"];
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:mutableReq delegate:self];
    [connection start];
  • 以NSURLSession为例:

      NSURL *httpDnsURL = [NSURL URLWithString:@"使用解析结果ip拼接的URL"];
      float timeOut = 设置的超时时间;
      NSMutableURLRequest *mutableReq = [NSMutableURLRequest requestWithURL:httpDnsURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval: timeOut];
      [mutableReq setValue:@"原域名" forHTTPHeaderField:@"host"];
      NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
      NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue currentQueue]];
      NSURLSessionTask *task = [session dataTaskWithRequest:mutableReq];
      [task resume];
  • 以curl为例:

    假设你要访问www.qq.com,通过HTTPDNS解析出来的IP为192.168.0.111,那么通过这个方式来调用即可:

      curl -H "host:www.qq.com" http://192.168.0.111/aaa.txt.
  • 以Unity的WWW接口为例:

      string httpDnsURL = "使用解析结果ip拼接的URL";
      Dictionary<string string> headers = new Dictionary<string string> ();
      headers["host"] = "原域名";
      WWW conn = new WWW (url, null, headers);
      yield return conn;
      if (conn.error != null) {
          print("error is happened:"+ conn.error);
      } else {
          print("request ok" + conn.text);
      }

  1. 检测本地是否使用了HTTP代理,如果使用了HTTP代理,建议不要使用HTTPDNS做域名解析
- 检测是否使用了HTTP代理:

  - (BOOL)isUseHTTPProxy {
      CFDictionaryRef dicRef = CFNetworkCopySystemProxySettings();
      const CFStringRef proxyCFstr = (const CFStringRef)CFDictionaryGetValue(dicRef, (const void*)kCFNetworkProxiesHTTPProxy);
      NSString *proxy = (__bridge NSString *)proxyCFstr;
      if (proxy) {
          return YES;
      } else {
          return NO;
      }
  }
  • 检测是否使用了HTTPS代理:

      - (BOOL)isUseHTTPSProxy {
          CFDictionaryRef dicRef = CFNetworkCopySystemProxySettings();
          const CFStringRef proxyCFstr = (const CFStringRef)CFDictionaryGetValue(dicRef, (const void*)kCFNetworkProxiesHTTPSProxy);
          NSString *proxy = (__bridge NSString *)proxyCFstr;
          if (proxy) {
              return YES;
          } else {
              return NO;
          }
      }

  • 实践场景


    1. Unity工程接入

    1. 将HTTPDNSUnityDemo/Assets/Plugins/Scripts下的HttpDns.cs文件拷贝到Unity对应Assets/Plugins/Scripts路径下

    2. 在需要进行域名解析的部分,调用HttpDns.GetAddrByName(string domain)或者HttpDns.GetAddrByNameAsync(string domain)方法

      1. 如使用同步接口HttpDns.GetAddrByName,直接调用接口即可;
      2. 如果使用异步接口HttpDns.GetAddrByNameAsync,还需设置回调函数onDnsNotify(string ipString),函数名可自定义

      并建议添加如下处理代码:

      string[] sArray=ipString.Split(new char[] {';'}); 
      if (sArray != null && sArray.Length > 1) {
          if (!sArray[1].Equals("0")) {
              //TODO 使用ipv6地址进行URL连接时,注意格式,需加方框号[ ]进行处理,例如:http://[64:ff9b::b6fe:7475]/
          } else if(!sArray [0].Equals ("0")) {
              //使用ipv4地址进行连接
          } else {
              //异常情况返回为0,0,建议重试一次
              HttpDns.GetAddrByName(domainStr);
          }
      }
      
    3. 将unity工程打包为xcode工程后,引入所需依赖库;

    4. 将HTTPDNSUnityDemo下的MSDKDnsUnityManager.h及MSDKDnsUnityManager.mm文件导入到工程中,注意以下地方需要与Unity中对应的GameObject名称及回调函数名称一致:

      Unity接入图片1

      Unity接入图片1

    2. Https场景下(非SNI)使用HttpDns解析结果

    原理

    在进行证书校验时,将IP替换成原来的域名,再进行证书验证。

    Demo示例

    • 以NSURLConnection接口为例:

      #pragma mark - NSURLConnectionDelegate
      - (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, &amp;result);
      return (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed);

      }

      • (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { if (!challenge) {

          return;

        }

        //URL里面的host在使用HTTPDNS的情况下被设置成了IP,此处从HTTP Header中获取真实域名 NSString *host = [[self.request allHTTPHeaderFields] objectForKey:@"host"]; if (!host) {

          host = self.request.URL.host;

        }

        //判断challenge的身份验证方法是否是NSURLAuthenticationMethodServerTrust(HTTPS模式下会进行该身份验证流程), //在没有配置身份验证方法的情况下进行默认的网络请求流程。 if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {

          if ([self evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:host]) {        
        
              //验证完以后,需要构造一个NSURLCredential发送给发起方    
              NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
              [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
          } else {
              //验证失败,取消这次验证流程
              [[challenge sender] cancelAuthenticationChallenge:challenge];
          }

        } else {

          //对于其他验证方法直接进行处理流程
          [[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge];

        } }

    • 以NSURLSession接口为例:

      #pragma mark - NSURLSessionDelegate
    • (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); }

    • (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential))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); }

    • 以Unity的WWW接口为例:

    将Unity工程导为Xcode工程后,打开Classes/Unity/WWWConnection.mm文件,修改下述代码:

    //const char* WWWDelegateClassName = "UnityWWWConnectionSelfSignedCertDelegate";
    const char* WWWDelegateClassName = "UnityWWWConnectionDelegate";
    

    为:

    const char* WWWDelegateClassName = "UnityWWWConnectionSelfSignedCertDelegate";
    //const char* WWWDelegateClassName = "UnityWWWConnectionDelegate";
    

    3. SNI(单IP多HTTPS证书)场景下使用HttpDns解析结果

    SNI(Server Name Indication)是为了解决一个服务器使用多个域名和证书的SSL/TLS扩展。它的工作原理如下:

    • 在连接到服务器建立SSL链接之前先发送要访问站点的域名(Hostname)。
    • 服务器根据这个域名返回一个合适的证书。

    上述过程中,当客户端使用HttpDns解析域名时,请求URL中的host会被替换成HttpDns解析出来的IP,导致服务器获取到的域名为解析后的IP,无法找到匹配的证书,只能返回默认的证书或者不返回,所以会出现SSL/TLS握手不成功的错误。

    由于iOS上层网络库NSURLConnection/NSURLSession没有提供接口进行SNI字段的配置,因此可以考虑使用NSURLProtocol拦截网络请求,然后使用CFHTTPMessageRef创建NSInputStream实例进行Socket通信,并设置其kCFStreamSSLPeerName的值。

    需要注意的是,使用NSURLProtocol拦截NSURLSession发起的POST请求时,HTTPBody为空。解决方案有两个:

    1. 使用NSURLConnection发POST请求。
    2. 先将HTTPBody放入HTTP Header field中,然后在NSURLProtocol中再取出来。

    具体示例参见Demo,部分代码如下:

    在网络请求前注册NSURLProtocol子类,在示例的SNIViewController.m中。

    // 注册拦截请求的NSURLProtocol
    [NSURLProtocol registerClass:[MSDKDnsHttpMessageTools class]];
    
    

    // 需要设置SNI的URL NSString *originalUrl = @"your url"; NSURL *url = [NSURL URLWithString:originalUrl]; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; NSArray *result = [[MSDKDns sharedInstance] WGGetHostByName:url.host]; NSString *ip = nil; if (result && result.count > 1) { if (![result[1] isEqualToString:@"0"]) { ip = result[1]; } else { ip = result[0]; } } // 通过HTTPDNS获取IP成功,进行URL替换和HOST头设置 if (ip) { NSRange hostFirstRange = [originalUrl rangeOfString:url.host]; if (NSNotFound != hostFirstRange.location) { NSString *newUrl = [originalUrl stringByReplacingCharactersInRange:hostFirstRange withString:ip]; request.URL = [NSURL URLWithString:newUrl]; [request setValue:url.host forHTTPHeaderField:@"host"]; } }

    // NSURLConnection例子 self.connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; [self.connection start];

    // NSURLSession例子 NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSArray *protocolArray = @[ [MSDKDnsHttpMessageTools class] ]; configuration.protocolClasses = protocolArray; NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]]; self.task = [session dataTaskWithRequest:request]; [self.task resume];

    // 注*:使用NSURLProtocol拦截NSURLSession发起的POST请求时,HTTPBody为空。 // 解决方案有两个:1. 使用NSURLConnection发POST请求。 // 2. 先将HTTPBody放入HTTP Header field中,然后在NSURLProtocol中再取出来。 // 下面主要演示第二种解决方案 // NSString *postStr = [NSString stringWithFormat:@"param1=%@&param2=%@", @"val1", @"val2"]; // [_request addValue:postStr forHTTPHeaderField:@"originalBody"]; // _request.HTTPMethod = @"POST"; // NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; // NSArray *protocolArray = @[ [CFHttpMessageURLProtocol class] ]; // configuration.protocolClasses = protocolArray; // NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]]; // NSURLSessionTask *task = [session dataTaskWithRequest:_request]; // [task resume];

    使用说明

    需调用以下接口设置需要拦截域名或无需拦截的域名:

    #pragma mark - SNI场景,仅调用一次即可,请勿多次调用
    /**
     SNI场景下设置需要拦截的域名列表
     建议使用该接口设置,仅拦截SNI场景下的域名,避免拦截其它场景下的域名
    
    

    @param hijackDomainArray 需要拦截的域名列表 */

    • (void) WGSetHijackDomainArray:(NSArray *)hijackDomainArray;

    /** SNI场景下设置不需要拦截的域名列表

    @param noHijackDomainArray 不需要拦截的域名列表 */

    • (void) WGSetNoHijackDomainArray:(NSArray *)noHijackDomainArray;
    • 如设置了需要拦截的域名列表,则仅会拦截处理该域名列表中的https请求,其它域名不做处理;
    • 如设置了不需要拦截的域名列表,则不会拦截处理该域名列表中的https请求;

    建议使用WGSetHijackDomainArray仅拦截SNI场景下的域名,避免拦截其它场景下的域名。

    We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.