njt*_*man 5 ssl objective-c ios cordova mknetworkkit
编辑2/6/14:
我创建了一个本地Apache Tomcat服务器来测试带有证书身份验证的SSL.我成功了!使用下面的两种方法,一切都按预期工作.(MKNetworkKit和自定义代码).虽然这确实告诉我我的代码正在运行,但我的原始问题仍未解决.我更新了问题的标题,以更具体地反映问题.有谁知道SAP Portal是否需要特殊设置来接受来自iOS应用程序的证书?请记住,在将CA和.p12导入共享密钥链后,我能够使用Safari移动设备成功进行身份验证,我只是在代码中失败(我现在知道代码可以工作,而不是使用门户网站).
我正在创建一个非常简单的iOS7 Cordova 3.2应用程序,其中包含一个自定义插件,通过仅提供.p12证书进行身份验证(无需基本身份验证或其他用户凭据)从SSL Web服务获取数据.我在物理iPad(没有模拟器)上执行所有测试.Web服务使用自签名证书存在于开发SAP NetWeaver门户框中.目前,我将服务器的CA导入iOS钥匙串以避免证书信任错误.出于测试目的,我的.p12证书在应用程序内部捆绑在mainBundle的根目录中.
尝试连接到Web服务时,我在控制台中收到以下错误:
CFNetwork SSLHandshake failed (-9825)
NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9825)
Error Domain=NSURLErrorDomain Code=-1205 "The server “myhostremoved.com” did not accept the certificate." UserInfo=0x14e99000 {NSErrorFailingURLStringKey=https://myhostremoved.com/sslwebservice/, NSErrorFailingURLKey=https://myhostremoved.com/sslwebservice/, NSLocalizedDescription=The server “myhostremoved.com” did not accept the certificate., NSUnderlyingError=0x14d9b1d0 "The server “myhostremoved.com” did not accept the certificate.", NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x14d94720>}
Run Code Online (Sandbox Code Playgroud)
根据Apple的文档站点,-9825错误引用了错误的证书.
有很多关于SO的问题与我想要做的事情有关,但没有一个与我所看到的错误有关.我以两种不同的方式处理代码的开发.
首先,我尝试使用已经在SO上的代码,使其适应我的用例.见下面的代码:
- (void)startConnection:(CDVInvokedUrlCommand*)command {
NSDictionary *options = [command.arguments objectAtIndex:0];
NSURL *serverURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@", [options objectForKey:@"host"]]];//hostname provided by Cordova plugin, but could just as easily be hardcoded here
NSMutableURLRequest *connectionRequest = [NSMutableURLRequest requestWithURL:serverURL];
NSURLConnection *connection = nil;
connection = [[NSURLConnection alloc] initWithRequest:connectionRequest delegate:self startImmediately:YES];
}
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
// gets a certificate from local resources
NSString *thePath = [[NSBundle mainBundle] pathForResource:@"mycert" ofType:@"p12"];
NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
SecIdentityRef identity;
// extract the ideneity from the certificate
[self extractIdentity :inPKCS12Data :&identity];
SecCertificateRef certificate = NULL;
SecIdentityCopyCertificate (identity, &certificate);
const void *certs[] = {certificate};
CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL);
// create a credential from the certificate and ideneity, then reply to the challenge with the credential
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:(__bridge NSArray*)certArray persistence:NSURLCredentialPersistencePermanent];
[challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
}
- (OSStatus)extractIdentity:(CFDataRef)inP12Data :(SecIdentityRef*)identity {
OSStatus securityError = errSecSuccess;
CFStringRef password = CFSTR("MyCertPassw0rd");
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 ident = CFArrayGetValueAtIndex(items,0);
const void *tempIdentity = NULL;
tempIdentity = CFDictionaryGetValue(ident, kSecImportItemIdentity);
*identity = (SecIdentityRef)tempIdentity;
}
if (options) {
CFRelease(options);
}
return securityError;
}
Run Code Online (Sandbox Code Playgroud)
在我的第二种方法中,我尝试使用MKNetworkKit库,它抽象出许多与证书接口所需的代码.您需要做的就是提供证书和密码的路径.再次,我得到与上面相同的错误.这段代码如下.
- (void)startConnection:(CDVInvokedUrlCommand*)command {
NSDictionary *options = [command.arguments objectAtIndex:0];
NSURL *serverURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@", [options objectForKey:@"host"]]];//hostname provided by Cordova plugin, but could just as easily be hardcoded here
MKNetworkEngine *engine = [[MKNetworkEngine alloc] initWithHostName:serverURL customHeaderFields:nil];
MKNetworkOperation *op = [engine operationWithPath:nil params:nil httpMethod:@"GET" ssl:YES];
NSString *thePath = [[NSBundle mainBundle] pathForResource:@"mycert" ofType:@"p12"];
[op setShouldContinueWithInvalidCertificate:YES];
op.clientCertificate = thePath;
op.clientCertificatePassword = @"MyCertPassw0rd";
[op addCompletionHandler:^(MKNetworkOperation *operation) {
NSLog(@"[operation responseData]-->>%@", [operation responseString]);
}errorHandler:^(MKNetworkOperation *errorOp, NSError* err) {
NSLog(@"MKNetwork request error : %@", [err localizedDescription]);
}];
[engine enqueueOperation:op];
}
Run Code Online (Sandbox Code Playgroud)
我使用这两种方法得到了同样的错误.有任何想法吗?
在代码中提供基本身份验证(绕过证书身份验证)时,一切都按预期工作,我没有收到任何错误.
我也尝试了上面所有相同的步骤,但使用.pfx文件而不是我的.p12证书,相同的错误.
SSL服务适用于移动Safari.我通过iPhone配置实用程序将.p12证书导入我的钥匙串,并通过移动safari测试了Web服务.一切都按预期工作,没有错误发生(也没有信任错误),我收到预期的输出.
我还能够使用rest-client实用程序在桌面上成功测试Web服务
我正在尝试使用objective-c中的.p12证书对SSL Web服务进行身份验证.我知道服务器和Web服务都使用auth的cert,但是当我尝试在objective-c中建立连接时,我一直收到错误,所以我的代码中必定存在错误.请帮忙!
我终于能够解决这个问题了。我在这里找到了答案 http://oso.com.pl/?p=207&lang=en
看起来证书被发送了两次,导致服务器出现错误。
如果上面的链接失效了,我已经在 SO 上找到了相同的解决方案(但是针对不同的问题和错误)。
使用客户端证书身份验证时,为什么我不断收到 NSURLErrorDomain Code=-1206?
最终,改变这一点:
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:(__bridge NSArray*)certsArray persistence:NSURLCredentialPersistenceNone];
Run Code Online (Sandbox Code Playgroud)
对此:
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:nil persistence:NSURLCredentialPersistenceNone];
Run Code Online (Sandbox Code Playgroud)
解决了我的问题。如果有人能够对这个问题提供更多见解,那就太好了。
| 归档时间: |
|
| 查看次数: |
4505 次 |
| 最近记录: |