关于https和ssl的原理,请到此处查看:http://blog.163.com/magicc_love/blog/static/185853662201321423527263/
由于项目需求,访问服务是https的,并且使用的是ssl加密方式
下面说明使用MKNetworkit网络库实现的代码:
- - (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"];
- MKNetworkOperation *op = [engine operationWithPath:[NSString stringWithFormat:@"/ManicureShop/api/order/pay/%@", sign] 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 = [NSDictionary dictionaryWithObject:@"testHttps"
- 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 voidvoid *tempIdentity = NULL;
- tempIdentity = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemIdentity);
- *outIdentity = (SecIdentityRef)tempIdentity;
- const voidvoid *tempTrust = NULL;
- tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust);
- *outTrust = (SecTrustRef)tempTrust;
- } else {
- NSLog(@"Failed with error code %d",(int)securityError);
- return NO;
- }
- return YES;
- }
下面说明一下使用AFNetworking网络库访问的方式:
- - (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;
- }
为了实现访问https tls加密方式,我也费了不少时间来查,这里写下此文章,希望对大家有用!