自签名 SSL 证书和 stringWithContentsOfURL

发布于 2024-09-24 09:09:53 字数 320 浏览 0 评论 0原文

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

这都是预期的行为。我知道如何使用 NSURLConnection 及其委托方法正确执行此操作,但我正在寻找短期修复而不是重写此代码。 (是的截止日期)

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

I am requesting some data from a server with NSString#stringWithContentsOfURL:. The server is using a self-signed certificate, so stringWithContentsOfURL: simply returns nil and does not give a change to accept the certificate.

This is all expected behaviour. I know how to properly do this with NSURLConnection and it's delegate methods instead, but I am looking for a shorter term fix instead of rewriting this code. (Yay deadlines)

So my question is, is it possible to import the self-signed certificate into the application's keychain, and will that cause stringWithContentsOfURL: to accept the self-signed certificate?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你对谁都笑 2024-10-01 09:09:53

我相信 Apple 有一个用于安装 SSL 证书的企业工具——它是交换邮件正常工作所必需的。

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

还有来自 Apple 的 AdvancedURLConnections 示例项目

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

I beleive that there is an enterprise tool from Apple for installing SSL certs -- it was necessary to get exchange mail working.

You may also be able to mail the .cer file to yourself, open on your iPhone and install it.

There is also the AdvancedURLConnections sample project from Apple

This sample demonstrates various
advanced networking techniques with
NSURLConnection. Specifically, it
demonstrates how to respond to
authentication challenges, how to
modify the default server trust
evaluation (for example, to support a
server with a self-signed
certificate), and how to provide
client identities.

对不⑦ 2024-10-01 09:09:53

没有办法绕过 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;

如果我愿意的话,我想我可以只调用一次。

There is no way to go around that SSL verification scheme, and after a while of trying and looking all over the place for a solution, I had to implement a class to do just that.

Since the advantage of NSString's stringWithContentsOfURL is to be synchronous, I had to make sure mine was as well. It's probably a little big for every purpose, but you get the gist of it.

@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

And it's used like this:

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

I guess I could make it just one call, if I wanted to.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文