变更记录
方案名称
网络 - iOS 访问 HTTPS SSL 和 TLS 双向加密
关键字
网络 \ HTTPS \ SSL \ TLS \ MKNetworkit \ AFNetworking
需求场景
- 访问 HTTPS 并且使用 TLS 加密的服务器。
参考链接
- 标哥的技术博客 - iOS访问HTTPS SSL和TLS双向加密
- 简书 - HTTPS接口加密和身份认证
详细内容
使用 MKNetworkit 实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| - (void)testClientCertificate { SecIdentityRef identity = NULL; SecTrustRef trust = NULL; NSString *p12 = [[NSBundle mainBundle] pathForResource:@"testClient" ofType:@"p12"]; NSData *PKCS12Data = [NSData dataWithContentsOfFile:p12]; [[self class] extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12Data]; NSString *url = @"https://218.244.131.231/ManicureShop/api/order/pay/%@"; NSDictionary *dic = @{@"request" : @{ @"orderNo" : @"1409282102222110030643", @"type" : @(2) } }; _signString = nil; NSData *postData = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:nil]; NSString *sign = [self signWithSignKey:@"test" params:dic]; NSMutableData *body = [postData mutableCopy]; NSLog(@"%@", [[NSString alloc] initWithData:body encoding:NSUTF8StringEncoding]); url = [NSString stringWithFormat:url, sign]; MKNetworkEngine *engine = [[MKNetworkEngine alloc] initWithHostName:@"218.244.131.231"]; NSString *path = [NSString stringWithFormat:@"/ManicureShop/api/order/pay/%@", sign]; MKNetworkOperation *op = [engine operationWithPath:path params:dic httpMethod:@"POST" ssl:YES]; op.postDataEncoding = MKNKPostDataEncodingTypeJSON; // 传JOSN // 这个是app bundle 路径下的自签证书 op.clientCertificate = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"testClient.p12"]; // 这个是自签证书的密码 op.clientCertificatePassword = @"testHttps"; // 由于自签名的证书是需要忽略的,所以这里需要设置为YES,表示允许 op.shouldContinueWithInvalidCertificate = YES; [op addCompletionHandler:^(MKNetworkOperation *completedOperation) { NSLog(@"%@", completedOperation.responseJSON); } errorHandler:^(MKNetworkOperation *completedOperation, NSError *error) { NSLog(@"%@", [error description]); }]; [engine enqueueOperation:op]; return; } // 下面这段代码是提取和校验证书的数据的 + (BOOL)extractIdentity:(SecIdentityRef *)outIdentity andTrust:(SecTrustRef*)outTrust fromPKCS12Data:(NSData *)inPKCS12Data { OSStatus securityError = errSecSuccess; // 证书密钥 NSDictionary *optionsDictionary = @{@"testHttps": (__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(@"Failed with error code %d",(int)securityError); return NO; } return YES; }
|
使用 AFNetworking 实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| - (void)testClientCertificate { SecIdentityRef identity = NULL; SecTrustRef trust = NULL; NSString *p12 = [[NSBundle mainBundle] pathForResource:@"testClient" ofType:@"p12"]; NSData *PKCS12Data = [NSData dataWithContentsOfFile:p12]; [[self class] extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12Data]; NSString *url = @"https://218.244.131.231/ManicureShop/api/order/pay/%@"; NSDictionary *dic = @{@"request" : @{ @"orderNo" : @"1409282102222110030643", @"type" : @(2) } }; _signString = nil; NSData *postData = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:nil]; NSString *sign = [self signWithSignKey:@"test" params:dic]; NSMutableData *body = [postData mutableCopy]; NSLog(@"%@", [[NSString alloc] initWithData:body encoding:NSUTF8StringEncoding]); url = [NSString stringWithFormat:url, sign]; AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; manager.requestSerializer = [AFJSONRequestSerializer serializer]; manager.responseSerializer = [AFJSONResponseSerializer serializer]; [manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"]; [manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; manager.responseSerializer.acceptableContentTypes = [NSSet setWithArray:@[@"application/json", @"text/plain"]]; manager.securityPolicy = [self customSecurityPolicy]; [manager POST:url parameters:dic success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"JSON: %@", responseObject); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"Error: %@", error); }]; } // 下面这段代码是处理SSL安全性问题的: /**** SSL Pinning ****/ - (AFSecurityPolicy*)customSecurityPolicy { NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"testClient" ofType:@"cer"]; NSData *certData = [NSData dataWithContentsOfFile:cerPath]; AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy]; [securityPolicy setAllowInvalidCertificates:YES]; [securityPolicy setPinnedCertificates:@[certData]]; [securityPolicy setSSLPinningMode:AFSSLPinningModeCertificate]; /**** SSL Pinning ****/ return securityPolicy; }
|
效果图
(无)
备注
(无)