自签名SSL证书和stringWithContentsOfURL

时间:2010-09-20 20:45:06

标签: ssl network-programming ios self-signed

我从NSString#stringWithContentsOfURL:的服务器请求一些数据。服务器使用的是自签名证书,因此stringWithContentsOfURL:只返回nil,并且不会更改以接受证书。

这是所有预期的行为。我知道如何使用NSURLConnection和它的委托方法正确地执行此操作,但我正在寻找一个较短期的修复而不是重写此代码。 (Yay截止日期)

所以我的问题是,是否可以将自签名证书导入应用程序的钥匙串,这会导致stringWithContentsOfURL:接受自签名证书吗?

2 个答案:

答案 0 :(得分:1)

我相信Apple有一个企业工具用于安装SSL证书 - 有必要让Exchange邮件正常工作。

您也可以将.cer文件邮寄给自己,在iPhone上打开并安装。

还有来自Apple的AdvancedURLConnections sample project

  

此示例演示了各种   先进的网络技术   NSURLConnection的。具体来说,它   演示了如何回应   身份验证挑战,如何   修改默认服务器信任   评估(例如,支持a   服务器带有自签名   证书),以及如何提供   客户身份。

答案 1 :(得分:1)

没有办法绕过那个SSL验证方案,经过一段时间的尝试和寻找解决方案的地方,我不得不实现一个类来做到这一点。

由于NSString的stringWithContentsOfURL的优势是同步的,我必须确保我的同样。对于各种目的来说,这可能有点大,但是你得到了它的要点。

@interface NZStringLoader : NSObject
@property (assign, readonly, nonatomic) BOOL done;
@property (strong, readonly, nonatomic) NSString *result;
@property (strong, readonly, nonatomic) NSURLConnection *conn;

- (id) initWithURL:(NSURL*)u;
- (void) loadSynchronously;

@end

@implementation NZStringLoader

@synthesize done = _done, result = _result, conn = _connection;

- (id) initWithURL:(NSURL*)u {
    NSURLRequest *req = [[NSURLRequest alloc] initWithURL:u
                                              cachePolicy:NSURLRequestReloadIgnoringCacheData
                                          timeoutInterval:10.0];
    _connection = [NSURLConnection connectionWithRequest:req delegate:self];
    _done = NO;

    return self;
}

- (void) loadSynchronously {
    [_connection start];

    while(!_done)
        [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:.15]];
}

#pragma mark -
#pragma mark NSURLConnectionDelegate

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    _done = YES;
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    RTLog(@"%@", [error localizedDescription]);
    _done = YES;
}

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
    return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
        [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];

    [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    if(_result == nil)
        _result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    else
        _result = [_result stringByAppendingString:[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]];
}

@end

它的使用方式如下:

    NZStringLoader *sl = [[NSStringLoader alloc] initWithURL:u];
    [sl loadSynchronously];
    result = sl.result;

如果我愿意的话,我想我只能拨打一个电话。