我正在编写一些执行http请求的API代码,我一直在使用[NSUrlConnection:sendAsynchronousRequest:queue:completionHandler]进行调用,因为这样可以很容易地编写简单的处理程序,同时也让我不必为每次调用都有不同的代表和不同的代表。
我遇到的问题是,似乎接受自签名证书的唯一方法是让一个委托实现一些函数,证明证书没问题。有没有办法用使用块的异步方法做到这一点?
答案 0 :(得分:3)
不,但代表电话并不是那么难。这是您需要的代码:
1)将此文件设为静态
static CFArrayRef certs;
2)在初始化中执行此操作:
// I had a crt certificate, needed a der one, so found this site:
// http://fixunix.com/openssl/537621-re-der-crt-file-conversion.html
// and did this from Terminal: openssl x509 -in crt.crt -outform der -out crt.der
NSString *path = [[NSBundle mainBundle] pathForResource:@"<your name>" ofType:@"der"];
assert(path);
NSData *data = [NSData dataWithContentsOfFile:path];
assert(data);
SecCertificateRef rootcert = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)data);
if(rootcert) {
const void *array[1] = { rootcert };
certs = CFArrayCreate(NULL, array, 1, &kCFTypeArrayCallBacks);
CFRelease(rootcert); // for completeness, really does not matter
} else {
NSLog(@"BIG TROUBLE - ROOT CERTIFICATE FAILED!");
}
3)然后添加此方法:
- (void)connection:(NSURLConnection *)conn didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
#pragma unused(conn)
// NSLog(@"didReceiveAuthenticationChallenge %@ FAILURES=%zd", [[challenge protectionSpace] authenticationMethod], (ssize_t)[challenge previousFailureCount]);
/* Setup */
NSURLProtectionSpace *protectionSpace = [challenge protectionSpace];
assert(protectionSpace);
SecTrustRef trust = [protectionSpace serverTrust];
assert(trust);
CFRetain(trust); // Don't know when ARC might release protectionSpace
NSURLCredential *credential = [NSURLCredential credentialForTrust:trust];
BOOL trusted = NO;
OSStatus err;
SecTrustResultType trustResult = 0;
err = SecTrustSetAnchorCertificates(trust, certs);
if (err == noErr) {
err = SecTrustEvaluate(trust, &trustResult);
if(err == noErr) {
// http://developer.apple.com/library/mac/#qa/qa1360/_index.html
switch(trustResult) {
case kSecTrustResultProceed:
case kSecTrustResultConfirm:
case kSecTrustResultUnspecified:
trusted = YES;
break;
}
}
}
CFRelease(trust);
// Return based on whether we decided to trust or not
if (trusted) {
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
} else {
NSLog(@"Trust evaluation failed");
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}