ios 证书验证

it2025-08-21  9

说明

这里我们所访问的是微信支付下的企业付款到零钱接口,该接口需要单向认证,我们需要从微信商户后台下载需要的证书(.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)