详解iOS开发 - 用AFNetworking实现https单向验证,双向验证

2020-01-18 18:52:58于海丽

4)发起请求


//第三步和这一步代码是放在一起的,请注意哦
  [_manager GET:url parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {

  } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
    NSLog(@"JSON: %@", dic);
  } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    NSLog(@"Error: %@", error);

    NSData *data = [error.userInfo objectForKey:@"com.alamofire.serialization.response.error.data"];
    NSString *str = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"%@",str);
  }];

另外还要加上一个方法:


+(BOOL)extractIdentity:(SecIdentityRef*)outIdentity andTrust:(SecTrustRef *)outTrust fromPKCS12Data:(NSData *)inPKCS12Data {
  OSStatus securityError = errSecSuccess;
  //client certificate password
  NSDictionary*optionsDictionary = [NSDictionary dictionaryWithObject:@"证书密码"
                                 forKey:(__bridge id)kSecImportExportPassphrase];

  CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
  securityError = SecPKCS12Import((__bridge CFDataRef)inPKCS12Data,(__bridge CFDictionaryRef)optionsDictionary,&items);

  if(securityError == 0) {
    CFDictionaryRef myIdentityAndTrust =CFArrayGetValueAtIndex(items,0);
    const void*tempIdentity =NULL;
    tempIdentity= CFDictionaryGetValue (myIdentityAndTrust,kSecImportItemIdentity);
    *outIdentity = (SecIdentityRef)tempIdentity;
    const void*tempTrust =NULL;
    tempTrust = CFDictionaryGetValue(myIdentityAndTrust,kSecImportItemTrust);
    *outTrust = (SecTrustRef)tempTrust;
  } else {
    NSLog(@"Failedwith error code %d",(int)securityError);
    return NO;
  }
  return YES;
}

没错,我们是要封装一下,可是要怎么封装呢?博主尝试了集中都失败了,真是百思不得解,相信主动去封装的开发者也会碰到封装后请求失败的问题,也许你成功了,但是这里需要注意一个在block内使用变量的问题,具体的可以去看博主怎么封装的。

到这里,新的AF请求https就已经结束了,想看封装的,Demo放在最后。

3.单向验证

说到这个,不得不说一下网上的很多方法,都把单向验证当作双向的,其实也是并不理解其原理,关于原理,请看这里
代码实现AF都是一样的:


//AF加上这句和下面的方法
  _manager.securityPolicy = [self customSecurityPolicy];



/**** SSL Pinning ****/
- (AFSecurityPolicy*)customSecurityPolicy {
  NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"cer"];
  NSData *certData = [NSData dataWithContentsOfFile:cerPath];
  AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
  [securityPolicy setAllowInvalidCertificates:YES];
  NSSet *set = [NSSet setWithObjects:certData, nil];
  [securityPolicy setPinnedCertificates:@[certData]];
  /**** SSL Pinning ****/
  return securityPolicy;
}