ios 证书验证

4 篇文章 0 订阅

说明

这里我们所访问的是微信支付下的企业付款到零钱接口,该接口需要单向认证,我们需要从微信商户后台下载需要的证书(.p12格式),然后将证书拖入工程中即可
注意:证书内嵌到app内是不安全的,这里只是演示,实际开发证书应该放服务器(.pm格式)

思路

首先第一步我们需要发起请求,然后这只请求代理,在代理中读取本地证书验证。

请求

NSMutableURLRequest *request=[[NSMutableURLRequest alloc]init];
    [request setURL:[NSURL URLWithString:url]];
    [request setHTTPMethod:@"POST"];
    
    NSString *contentType=[NSString stringWithFormat:@"text/xml"];
    [request addValue:contentType forHTTPHeaderField:@"Content-Type"];
    
    NSMutableData *postBody=[NSMutableData data];
    [postBody appendData:[[NSString stringWithFormat:
                           @"<xml><mch_appid>%@</mch_appid><mchid>%@</mchid><nonce_str>%@</nonce_str><partner_trade_no>%@</partner_trade_no><openid>%@</openid><check_name>%@</check_name><amount>%d</amount><desc>%@</desc><sign>%@</sign></xml>",self.mch_appid,self.mchid,self.nonce_str,self.partner_trade_no,self.openid,self.check_name,self.amount,self.desc,self.sign] dataUsingEncoding:NSUTF8StringEncoding]];
    
    [request setHTTPBody:postBody];
    
    NSString *bodyStr=[[NSString alloc]initWithData:postBody encoding:NSUTF8StringEncoding];
    NSLog(@"********提交表单信息 post body: %@",bodyStr);
    NSURLSessionConfiguration * config = [NSURLSessionConfiguration defaultSessionConfiguration];
    //config.TLSMaximumSupportedProtocol = kTLSProtocol1;
    NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    //NSURLSession *session=[NSURLSession sharedSession];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSLog(@"返回的数据 data:%@",data);
       // NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
        
        if(error)
        {  NSLog(@"error:%@",error.description);
            return;
        }
    }];
    [task resume];

这里我们发起的请求时POST,请求的参数是xml格式的,NSURLSession的代理(delegate)设置self,因为self实现了NSURLSessionDelegate接口

@interface HttpUtils:NSObject<NSURLSessionDelegate>

代理

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
    NSLog(@"证书认证");
    NSLog(@"didReceiveChallenge: %@", challenge.protectionSpace.authenticationMethod);
    
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate]) {

        NSLog(@"challenged for client certificate");

          NSString *sslCertName = @"apiclient_cert";
          NSString *path2 = [[NSBundle mainBundle] pathForResource:sslCertName ofType:@"p12"];
          NSData *p12data = [NSData dataWithContentsOfFile:path2];

          CFDataRef inP12data = (__bridge CFDataRef) p12data;

          SecIdentityRef myIdentity;
          SecTrustRef myTrust;

          extractIdentityAndTrust(inP12data, &myIdentity, &myTrust);

          SecCertificateRef myCertificate;
          SecIdentityCopyCertificate(myIdentity, &myCertificate);
          const void *certs[] = {myCertificate};
          CFArrayRef certsArray = CFArrayCreate(NULL, certs, 1, NULL);

          CFRelease(myCertificate);

          secureCredential = [NSURLCredential credentialWithIdentity:myIdentity
                                                        certificates:(__bridge NSArray *) certsArray
                                                         persistence:NSURLCredentialPersistencePermanent];

        CFRelease(certsArray);

        [[challenge sender] useCredential:secureCredential forAuthenticationChallenge:challenge];

        completionHandler(NSURLSessionAuthChallengeUseCredential, secureCredential);
      }

      else if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {

        NSLog(@"challenged for server trust");

        [challenge.sender useCredential:[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust]
             forAuthenticationChallenge: challenge];

        completionHandler(NSURLSessionAuthChallengeUseCredential,
                          [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
      } else {

        NSLog(@"other challenge");

        if ([challenge previousFailureCount] == 0) {

          [[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge];

        } else {

          [[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge];
          completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge,nil);
        }

      }
}
OSStatus extractIdentityAndTrust(CFDataRef inP12data, SecIdentityRef *identity, SecTrustRef *trust)
{
  OSStatus securityError = errSecSuccess;

  CFStringRef password = CFSTR("1577168641");
  const void *keys[] = { kSecImportExportPassphrase };
  const void *values[] = { password };

  CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);

  CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);

  securityError = SecPKCS12Import(inP12data, options, &items);

  if (securityError == 0) {
    CFDictionaryRef myIdentityAndTrust = (CFDictionaryRef)CFArrayGetValueAtIndex(items, 0);
    const void *tempIdentity = NULL;
    tempIdentity = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemIdentity);
    *identity = (SecIdentityRef)tempIdentity;
    const void *tempTrust = NULL;
    tempTrust = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemTrust);
    *trust = (SecTrustRef)tempTrust;
  }

  if (options) {
    CFRelease(options);
  }

  return securityError;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值