AFNetworking相关(二)

482 阅读3分钟

Http版本

  • 0.9 实现Get请求
  • 1.0 增加POST,HEAD
    • 缺点:每一个TCP只能发送一次请求,每次连接耗费性能
  • 1.1 增加keep-alive
    • 短时间内保持连接,超时再关闭连接
    • 客户端可以同时发送多个请求,但服务器只能依次响应
  • 2.0
    • header压缩,gzip
    • 多工,多个请求同时响应,防止对头堵塞
    • 自推送.建立连接后服务器主动推送数据
    • 无状态

Http缺点

  • 内容明文传输,不安全,易被监听,不安全,不稳定(丢数据无法找回)
  • 不验证身份,任何人都可以访问,DoS攻击
  • 数据完整性无法验证,可以篡改内容

Https

  • http+加密+认证+完整保护
  • 加密 (对称+非对称)
  • 对称加密(内容)
  • 非对称加密(RSA,加密对称加密的秘钥)
  • CA证书(收费,无需额外操作) 自签证书(免费,需要配置)

AFSecurityPolicy

  • 作用是验证HTTPS证书是否有效
  • 使用方法:
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"https" ofType:@"cer"];
NSData *data = [NSData dataWithContentsOfFile:cerPath];
NSSet *cerSet = [NSSet setWithObject:data];
AFSecurityPolicy *security = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:cerSet];
[AFSecurityPolicy defaultPolicy];
security.allowInvalidCertificates = YES;
security.validatesDomainName = NO;

AFN证书验证流程

  • 收集公钥集合
  • 收到身份验证请求
  • -(void)URLSession:didReceiveChallenge:completionHandler
  • 根据配置判断是否验证服务器证书
  • 根据配置判断是否验证域名
  • 评估指定证书和策略的信任度:AFServerTrustlsValid
  • 证书评估通过,继续判断Pinning Mode:
  • AFSSLPinningModeNone 无条件信任,不允许,返回NO
  • AFSSLPinningModeCertificate 对比服务器证书和本地证书
  • AFSSLPinningModePublickey 对比服务证书和本地证书公钥
  • 是否包含公钥

AFNetworkReachability

  • 基础用法
AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager manager];
[manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
    switch (status) {
        case AFNetworkReachabilityStatusUnknown:
            NSLog(@"不明网络");
            break;
        case AFNetworkReachabilityStatusNotReachable:
            NSLog(@"没有网络");
            break;
        case AFNetworkReachabilityStatusReachableViaWWAN:
            NSLog(@"蜂窝网络");
            break;
        case AFNetworkReachabilityStatusReachableViaWiFi:
            NSLog(@"WiFi"); //光纤
            break;
        default:
            break;
    }
}];
[manager startMonitoring];
  • 底层为原生SystemConfigration库内的SCNetworkReachabilityRef
  • startMonitoring内做了什么?
- (void)startMonitoring {
    [self stopMonitoring];
    if (!self.networkReachability) {
        return;
    }
    __weak __typeof(self)weakSelf = self;
    // 创建一个在每次网络状态改变时的回调
    AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
        __strong __typeof(weakSelf)strongSelf = weakSelf;
        /*
        每次回调被调用时
        重新设置 networkReachabilityStatus 属性
        再调用 networkReachabilityStatusBlock
        */
        strongSelf.networkReachabilityStatus = status;
        if (strongSelf.networkReachabilityStatusBlock) {
            strongSelf.networkReachabilityStatusBlock(status);
        }
    };
    SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL};
    // 为SCNetworkReachability添加回调函数 在状态变化的时候会调用这个回调
    // 这个方法中还要一个回调函数,和一个 SCNetworkReachabilityContext 。回调函数用来当网络状态发生变化时,让系统进行回调。
    SCNetworkReachabilitySetCallback(self.networkReachability, AFNetworkReachabilityCallback, &context);
    // 在设置完了回调函数后,将networkReachability加入到runloop中,达到实时监听的目的
    // 这里是kCFRunLoopCommonModes,这样当用户操作UI的时候,也会继续监听。和NSTimer的使用类似,将定时器添加到这个模式的runloop中时,滑动事件就不会中断定时器的计时。
    SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
    // 在异步线程 发送一次当前的网络状态。
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{
        SCNetworkReachabilityFlags flags; // status
        if (SCNetworkReachabilityGetFlags(self.networkReachability, &flags)) {
            AFPostReachabilityStatusChange(flags, callback);
        }
    });
}
  • 监听网络权限状态
- (void)cellularData {
    CTCellularData *cellularData = [[CTCellularData alloc] init];
    cellularData.cellularDataRestrictionDidUpdateNotifier = ^(CTCellularDataRestrictedState state){
        switch (state) {
            case kCTCellularDataRestricted:
                {
                    NSLog(@"网络权限被拒绝");
                }
            break;
            case kCTCellularDataNotRestricted:
                {
                    NSLog(@"网络权限正常,可以监控网络状态");
                }
            case kCTCellularDataRestrictedStateUnknown:
                {
                    NSLog(@"未知状态");
                }
            default:
            break;
        }
    };
}