美文网首页
关于AFN内AFSecurityPolicy的evaluateS

关于AFN内AFSecurityPolicy的evaluateS

作者: 破弓 | 来源:发表于2017-10-13 13:31 被阅读41次

    以下是AFN内AFSecurityPolicyevaluateServerTrust:forDomain:方法的代码.我们看了好几遍,觉得太繁琐了吧!我根据我了解的AFSecurityPolicy各项属性的功能,改写了一个简单的版本,还烦请各位前辈看看,这样的改写行不行?

    • 源码
    - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust
          forDomain:(NSString *)domain
    {
     if (domain && self.allowInvalidCertificates && self.validatesDomainName && (self.SSLPinningMode == AFSSLPinningModeNone || [self.pinnedCertificates count] == 0)) {
      // https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/OverridingSSLChainValidationCorrectly.html
      //  According to the docs, you should only trust your provided certs for evaluation.
      //  Pinned certificates are added to the trust. Without pinned certificates,
      //  there is nothing to evaluate against.
      //
      //  From Apple Docs:
      //          "Do not implicitly trust self-signed certificates as anchors (kSecTrustOptionImplicitAnchors).
      //           Instead, add your own (self-signed) CA certificate to the list of trusted anchors."
      NSLog(@"In order to validate a domain name for self signed certificates, you MUST use pinning.");
      return NO;
     }
     
     NSMutableArray *policies = [NSMutableArray array];
     if (self.validatesDomainName) {
      [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)];
     } else {
      [policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()];
     }
     
     SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies);
     
     if (self.SSLPinningMode == AFSSLPinningModeNone) {
      return self.allowInvalidCertificates || AFServerTrustIsValid(serverTrust);
     } else if (!AFServerTrustIsValid(serverTrust) && !self.allowInvalidCertificates) {
      return NO;
     }
     
     switch (self.SSLPinningMode) {
      case AFSSLPinningModeNone:
      default:
       return NO;
      case AFSSLPinningModeCertificate: {
       NSMutableArray *pinnedCertificates = [NSMutableArray array];
       for (NSData *certificateData in self.pinnedCertificates) {
        [pinnedCertificates addObject:(__bridge_transfer id)SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateData)];
       }
       SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCertificates);
       
       if (!AFServerTrustIsValid(serverTrust)) {
        return NO;
       }
       
       // obtain the chain after being validated, which *should* contain the pinned certificate in the last position (if it's the Root CA)
       NSArray *serverCertificates = AFCertificateTrustChainForServerTrust(serverTrust);
       
       for (NSData *trustChainCertificate in [serverCertificates reverseObjectEnumerator]) {
        if ([self.pinnedCertificates containsObject:trustChainCertificate]) {
         return YES;//zc read:有一个对得上就,代表验证成功
        }
       }
       
       return NO;
      }
      case AFSSLPinningModePublicKey: {
       NSUInteger trustedPublicKeyCount = 0;
       NSArray *publicKeys = AFPublicKeyTrustChainForServerTrust(serverTrust);
       
       for (id trustChainPublicKey in publicKeys) {
        for (id pinnedPublicKey in self.pinnedPublicKeys) {
         if (AFSecKeyIsEqualToKey((__bridge SecKeyRef)trustChainPublicKey, (__bridge SecKeyRef)pinnedPublicKey)) {
          trustedPublicKeyCount += 1;
         }
        }
       }
       return trustedPublicKeyCount > 0;//zc read:有一个对得上就,代表验证成功
      }
     }
     
     return NO;
    }
    
    • 属性认识
    /*
     1.SSLPinningMode 模式:默认==>AFSSLPinningModeNone
     AFSSLPinningModeNone==>不进行验证
     AFSSLPinningModePublicKey==>用本地的证书的公钥进行验证
     AFSSLPinningModeCertificate==>用本地的证书进行验证
     */
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
    
    //2.allowInvalidCertificates 是否允许自签名:默认==>NO
    securityPolicy.allowInvalidCertificates = NO;
    
    //3.validatesDomainName 是否验证域名:默认==>YES
    securityPolicy.validatesDomainName = NO;
    
    //4.pinnedCertificates 本地导入的证书:默认==>app包内所有的.cer全会被添加进来
    NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"cer"];
    NSData *certData = [NSData dataWithContentsOfFile:cerPath];
    securityPolicy.pinnedCertificates = [NSSet setWithObject:certData];
    
    • 改写
    - (BOOL)zc_evaluateServerTrust:(SecTrustRef)serverTrust
                      forDomain:(NSString *)domain
    {
        /*part1:*/
        //验证签名,却没有签名 返回NO
        if (self.validatesDomainName && domain == nil) {
            return NO;
        }
        
        //验证证书或公钥 却没有导入证书 返回NO
        if (self.SSLPinningMode != AFSSLPinningModeNone && self.pinnedCertificates.count <= 0) {
            return NO;
        }
        
        /*part2:*/
        //设置验证策略
        NSMutableArray *policies = [NSMutableArray array];
        if (self.validatesDomainName) {
            [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)];
        } else {
            [policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()];
        }
        SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies);
        
        /*part3:*/
        //做分支判断
        if (self.SSLPinningMode == AFSSLPinningModeNone){
            return self.allowInvalidCertificates || AFServerTrustIsValid(serverTrust);
        }else{
            
            if (!AFServerTrustIsValid(serverTrust) && !self.allowInvalidCertificates) {
                return NO;
            }
            
            if (self.SSLPinningMode == AFSSLPinningModePublicKey){
                NSUInteger trustedPublicKeyCount = 0;
                NSArray *publicKeys = AFPublicKeyTrustChainForServerTrust(serverTrust);
                
                for (id trustChainPublicKey in publicKeys) {
                    for (id pinnedPublicKey in self.pinnedPublicKeys) {
                        if (AFSecKeyIsEqualToKey((__bridge SecKeyRef)trustChainPublicKey, (__bridge SecKeyRef)pinnedPublicKey)) {
                            trustedPublicKeyCount += 1;
                        }
                    }
                }
                return trustedPublicKeyCount > 0;//zc read:有一个对得上就,代表验证成功
            }else if (self.SSLPinningMode == AFSSLPinningModeCertificate){
                
                
                NSMutableArray *pinnedCertificates = [NSMutableArray array];
                for (NSData *certificateData in self.pinnedCertificates) {
                    [pinnedCertificates addObject:(__bridge_transfer id)SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateData)];
                }
                SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCertificates);
                
                if (!AFServerTrustIsValid(serverTrust)) {
                    return NO;
                }
                
                NSArray *serverCertificates = AFCertificateTrustChainForServerTrust(serverTrust);
                
                for (NSData *trustChainCertificate in [serverCertificates reverseObjectEnumerator]) {
                    if ([self.pinnedCertificates containsObject:trustChainCertificate]) {
                        return YES;//zc read:有一个对得上就,代表验证成功
                    }
                }
            }
        }
        
        return NO;
    }
    

    相关文章

      网友评论

          本文标题:关于AFN内AFSecurityPolicy的evaluateS

          本文链接:https://www.haomeiwen.com/subject/akkzyxtx.html