https 上的 NSURLConnection 同步请求

Posted

技术标签:

【中文标题】https 上的 NSURLConnection 同步请求【英文标题】:NSURLConnection synchronous request on https 【发布时间】:2011-06-04 12:37:30 【问题描述】:

谁能告诉我如何同步调用 https 服务器?我可以使用以下委托方法在 https 服务器上执行异步请求。

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge

但我需要同步。

【问题讨论】:

【参考方案1】:

//对请求进行编码

NSData *postData = [xmlText dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];

**//Calculating length of request**
NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]];

NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:requestUrlString]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/xml" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:postData];
NSURLResponse* response;
NSError* error = nil;

//Capturing server response
NSData* result = [NSURLConnection sendSynchronousRequest:request  returningResponse:&response error:&error];

【讨论】:

如果有数据也支持国际字符,例如:德语、意大利语等,最好使用NSUTF8StringEncoding。否则上述方法绝对完美.. 别忘了表情符号,它们也需要 UTF8 ;) 这家伙需要一个依赖于实例的函数调用,以便提供委托以响应 https 挑战【参考方案2】:
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error

NSUrlConnection 中的 https 应该可以正常工作。

如果您想提供凭据,它们需要成为 url 的一部分:(https://username:password@domain.tld/api/user.json)。

无法提供NSURLConnection 委托,因此如果您需要一些非标准的身份验证处理,则需要异步进行。

【讨论】:

这家伙需要一个依赖于实例的函数调用,以便提供委托以响应 https 挑战 谢谢 :) 就是这么简单。【参考方案3】:

我就是这样做的: 而不是

[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]

我基于包含的类创建了相同的方法实例,因为我们需要一个委托。并且不要使其成为单例,因此每个连接都有其独立变量,因为如果我们不这样做,并且两个连接恰好在另一个完成之前被调用,那么接收到的数据和循环的处理将不可恢复地交织在一起.

[[ClassNameHere new] sendSynchronousRequest:request returningResponse:&response error:&error]

这样我可以创建一个 NSUrl 连接并处理它(以同步方式,我们将看到如何)所以我不必更改任何以前编写的代码。

- (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse *__strong*)response error:(NSError *__strong*)error

    _finishedLoading=NO;
    _receivedData=[NSMutableData new];
    _error=error;
    _response=response;

    NSURLConnection*con=[NSURLConnection connectionWithRequest:request delegate:self];
    [con start];
    CFRunLoopRun();

    return _receivedData;



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


- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 

    //handle the challenge


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

    *_response=response;


- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

    [_receivedData appendData:data];


- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error

    *_error=error;
    CFRunLoopStop(CFRunLoopGetCurrent());


- (void)connectionDidFinishLoading:(NSURLConnection *)connection

    CFRunLoopStop(CFRunLoopGetCurrent());

诀窍在于 CFRunLoopRun() 和 CFRunLoopStop(CFRunLoopGetCurrent()) 我希望它在未来对其他人有所帮助。

【讨论】:

我不会问为什么有人会回答一个有 250 年历史的问题,尤其是那个问题 ;) 但更重要的是,我想提一下,您的代码没有正确验证,并且不安全.所以,如果这只是为了摆脱证书而测试代码,这没关系。对于生产来说,这是一个安全风险。 在这里我遇到了和他一样的问题,我必须在开发后期连接到 https。而且我已经有了使用同步请求的数据层。为了适应服务器的挑战,我们必须让它异步,而将数据层重新制作为同步会很麻烦。此代码实际上以同步异步 :) 方式处理身份验证。因此数据(模型)层仍然完好无损,没有任何修改。 现在关于挑战处理的安全性。我读了这篇文章:developer.apple.com/library/ios/#technotes/tn2232/_index.html#//… 我的情况不是我的服务器有一个经过验证的证书,它是自签名的,它将保持这种状态。并且没有服务器证书的父 CA。所以要么这个,要么下载证书并比较数据。而且我认为这两种方法都具有相同的攻击漏洞。所以我们必须与服务器合作以确保更安全。 首选使用根 CA 验证证书。自签名证书可能不那么安全并且存在其他问题(当它们更新时,您也需要更新您的客户端)。你仍然可以自己创建这个 CA——你并不总是需要一个昂贵的可信第三方。我已经发布了一个答案如何verify a self-sigend certificate 是的,这是真的:/ 您需要设置锚点,然后进行评估。但是,创建 CA 和证书是一个不同的主题。您可能会发现这个gist 很有用。

以上是关于https 上的 NSURLConnection 同步请求的主要内容,如果未能解决你的问题,请参考以下文章

AFNetworking/NSURLConnection HTTPS 保持活动显示奇怪的行为

清除 iOS 应用程序上的 NSUrlConnection 缓存?

NSURLConnection 上的 Apple SDK 文档中存在错误或混淆?

使用 NSURLConnection 和 HTTPS 发送 POST

iOS笔记—NSURLConnection怎么把http改为https

在同步调用上强制 NSUrlConnection 超时