JC专题Des's iOS iOS开发 之 代码

iOS AFNetworking/NSURLConnection

2016-04-19  本文已影响698人  42vio

使用AFNetworking来支持HTTPS

+ (AFSecurityPolicy*)customSecurityPolicy
{
    // 先导入证书
    NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"Robert Laurence.cer" ofType:nil];//证书的路径
    NSData *certData = [NSData dataWithContentsOfFile:cerPath];
    
    // AFSSLPinningModeCertificate 使用证书验证模式
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
    
    // allowInvalidCertificates 是否允许无效证书(也就是自建的证书),默认为NO  如果是需要验证自建证书,需要设置为YES
    securityPolicy.allowInvalidCertificates = YES;
  
    //validatesDomainName 是否需要验证域名,默认为YES;
    //假如证书的域名与你请求的域名不一致,需把该项设置为NO;如设成NO的话,即服务器使用其他可信任机构颁发的证书,也可以建立连接,这个非常危险,建议打开。
    //置为NO,主要用于这种情况:客户端请求的是子域名,而证书上的是另外一个域名。因为SSL证书上的域名是独立的,假如证书上注册的域名是www.google.com,那么mail.google.com是无法验证通过的;当然,有钱可以注册通配符的域名*.google.com,但这个还是比较贵的。
    //如置为NO,建议自己添加对应域名的校验逻辑。
    securityPolicy.validatesDomainName = NO;
    
    securityPolicy.pinnedCertificates = @[certData];
    
    return securityPolicy;
}
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];

    // 加上这行代码,https ssl 验证。
    manager.securityPolicy = [self customSecurityPolicy];

    [manager GET:url parameters:params progress:^(NSProgress * downloadProgress) {
    } success:^(NSURLSessionDataTask * task, id  responseObject) ]{
    } failure:^(NSURLSessionDataTask * task, NSError * error) {
    }];

使用NSURLConnection支持HTTPS的实现

// 通过系统默认验证流程来验证证书
NSURL * httpsURL = [NSURL URLWithString:@"https://www.google.com"];
self.connection = [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:httpsURL] delegate:self];
//回调
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 
{ 
    //1 获取trust object
    SecTrustRef trust = challenge.protectionSpace.serverTrust; 
    SecTrustResultType result;
    //2 SecTrustEvaluate对trust进行验证
    OSStatus status = SecTrustEvaluate(trust, &result);
    if(status == errSecSuccess &&(result == kSecTrustResultProceed ||  
    result == kSecTrustResultUnspecified)) {  
    //3 验证成功,生成NSURLCredential凭证cred,告知challenge的sender使用这个凭证来继续连接   
    NSURLCredential *cred = [NSURLCredential credentialForTrust:trust];      
    [challenge.sender useCredential:cred forAuthenticationChallenge:challenge];    
    } 
    else
     {  
    //4 验证失败,取消这次验证流程
    [challenge.sender cancelAuthenticationChallenge:challenge]; 
    }
}
// 自建证书
NSString * cerPath = [[NSBundle mainBundle] pathForResource:@"Robert Laurence.cer" ofType:nil]; //证书的路径
NSData * cerData = [NSData dataWithContentsOfFile:cerPath];
SecCertificateRef certificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(cerData));
self.trustedCertificates = @[CFBridgingRelease(certificate)];
//回调
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
    //1 获取trust object
    SecTrustRef trust = challenge.protectionSpace.serverTrust;
    SecTrustResultType result;
    //注意:这里将之前导入的证书设置成下面验证的Trust Object的anchor certificate
    SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)self.trustedCertificates);
    //2 SecTrustEvaluate会查找前面SecTrustSetAnchorCertificates设置的证书或者系统默认提供的证书,对trust进行验证
    OSStatus status = SecTrustEvaluate(trust, &result);
    if (status == errSecSuccess &&
        (result == kSecTrustResultProceed ||
        result == kSecTrustResultUnspecified)) {
         
        //3 验证成功,生成NSURLCredential凭证cred,告知challenge的sender使用这个凭证来继续连接
        NSURLCredential *cred = [NSURLCredential credentialForTrust:trust];
        [challenge.sender useCredential:cred forAuthenticationChallenge:challenge];
         
    } else {
        //4 验证失败,取消这次验证流程
        [challenge.sender cancelAuthenticationChallenge:challenge];
  }
}
上一篇下一篇

猜你喜欢

热点阅读