繁体   English   中英

sendAsynchronousRequest:queue:completionHandler:具有委托方法

[英]sendAsynchronousRequest:queue:completionHandler: With Delegate Methods

我有一台安装了自签名SSL证书的服务器。 但是,一旦我调用以下方法,它不会得到任何响应。 一旦将URL更改回http,就可以使用。

- (void)getAccountInfoWithCompletion:(void (^)(NSDictionary *json_response, NSError *error))completion
{
    NSURLRequest *request = [NSURLRequest requestWithURL:
                             [NSURL URLWithString:
                              [NSString stringWithFormat:@"%@/api/account/%d/get_info", BASE_HOST_URL_IP, [self getUserID]]
                            ]];

    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
        if (error)
        {
            if (completion)
            {
                //completion(@"error", error);
            }
        } else {
            NSString *response_string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            NSDictionary *json_object = [NSJSONSerialization JSONObjectWithData:[response_string dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];

            if (completion)
            {
                completion(json_object, error);
            }
        }
    }];
}

我之所以成为代表,是因为我可以在自己的应用中使用自签名证书。 以下教程是我正在使用的教程,但是后来我意识到我不能将其委托与完成处理方法一起使用。 我需要保留completionHandler方法。

http://www.cocoanetics.com/2010/12/nsurlconnection-with-self-signed-certificates/

为了收到SSL站点的响应,我该怎么办?

在您描述的情况下,(几乎)您必须使用委托。

这里发生的是sendAsynchronousRequest:queue:completion:使用URL加载系统的默认行为。 URL加载系统会看到您的自签名证书,无法对其进行验证,因此它无法信任它-并且将无法连接。 您应该看到NSError传递给完成处理程序,该处理程序填充了有关该问题的信息。

技术说明2232:HTTPS服务器信任评估中对此进行了详细描述。

要允许您的自签名证书,您不能使用sendAsynchronousRequest:queue:completion:除非您有办法使自签名证书受信任并存储在钥匙串中-在iOS上,这仅在托管设备中才实用。 对于测试,仅用于测试,您可以使用私有的Apple API来更改默认的信任行为。

对于生产代码,必须实现NSURLConnectionDelegate,该NSURLConnectionDelegate可以处理对服务器提供的凭据的评估并允许您的自签名证书。 在技​​术说明2232中也对此进行了概述(如果没有对此进行概述)。如果未正确实施此操作,则可能会在应用中创建一个安全漏洞-不好,mmmmmk?

我不建议遵循您参考的《助剂学》的指导。 该材料已经过时并且质量令人怀疑。 请参考NSURLConnectionDelegate的文档和提及的Technote 2232 如果您想对一般的移动应用传输级安全性的更多信息,也有很多 资源可用。

如果仍然要使用自签名证书,则可以实现SSL公钥固定,以将远程(自签名)公钥与应用程序中存储的已知本地值进行匹配。 这比仅匹配主机名要好得多。 让你开始一些示例代码是在这里

ViewController.h:

@interface ViewController : UIViewController <NSURLSessionDelegate>

@end

ViewController.m:

- (void)getAccountInfoWithCompletion:(void (^)(NSDictionary *json_response, NSError *error))completion
{
    NSURLRequest *request = [NSURLRequest requestWithURL:
                             [NSURL URLWithString:
                              [NSString stringWithFormat:@"%@/api/account/%d/get_info", BASE_HOST_URL_IP, [self getUserID]]
                              ]];

    NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration ephemeralSessionConfiguration];
    defaultConfigObject.requestCachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData;

    NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue: [NSOperationQueue mainQueue]];

    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;

    NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithRequest:request
                                                       completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
    {
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

        if (error == nil && data != nil)
        {
            NSString *response_string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            NSDictionary *json_object = [NSJSONSerialization JSONObjectWithData:[response_string dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];

            if (completion)
            {
                completion(json_object, error);
            }
        }
    }];
    [dataTask resume];
}

新的漂亮的委托方法,使我们可以代替NSURLConnection的sendAsynchronousRequest方法(无法处理SSL)

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler
{
    NSString *host = challenge.protectionSpace.host;

    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
    {
        if ([host rangeOfString:@"yourHost.net"].location != NSNotFound)
        {
            completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
        }
        else
        {
            completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge,nil);
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM