当didReceiveChallenge方法调用时,应用程序冻结

时间:2016-04-21 21:26:53

标签: ios nsurlsession nsurlcredential

我正在尝试使用自签名证书连接到API进行测试。

  -(NSData*)getDataFromPostRequestWithHeaders:(NSDictionary*)headers      withPostData:(NSData*)postData fromURL:(NSString*)urlString
    {
    __block NSData* responseData;

    NSLog(@"URL is %@", urlString);
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]
                                                           cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                       timeoutInterval:10.0];
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:postData];
    [request setAllHTTPHeaderFields:headers];

    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
   // [config setHTTPAdditionalHeaders:headers];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
    NSLog(@"%@", @"NSURLSession started successfully");
    // I.e. no I do not need to have a queue of sessions running in parallel currently.
   NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
                                                completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
                                            {
                                                NSLog(@"%@", @"completionHandler called successfully");
                                                    if (error) {
                                                        NSLog(@"Error whilst executing post request: %@", error);
                                                    } else {
                                                        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
                                                        NSLog(@"HTTP response from this request is %@", httpResponse);
                                                        responseData = data;
                                                    }
                                                }];
    [dataTask resume];

    return responseData;
}

这是我的didReceiveChallenge()方法:

-(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler
{
    NSLog(@"%@", @"didReceiveChallenge method of NSURLSessionDelegate called successfully");
   if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
    {
        if ([challenge.protectionSpace.host isEqualToString:@"https://dongu.ravenlabs.co.uk"])
        {
            NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
            completionHandler(NSURLSessionAuthChallengeUseCredential, credential); // I.e. if it is this domain, then yes we can trust it.
        }
    }
}

第一个在登录方法中调用,如下所示:

-(NSString*)loginUserAndRetrieveSessionID:(NSString*)userName withPassword:(NSString*)password
{
    __block NSDictionary *responseDict;
   NSDictionary *loginHeaders = @{ @"content-type": @"application/json",
                               @"accept": @"application/json",
                               @"cache-control": @"no-cache",
                               };
    NSDictionary *parameters = @{ @"login": userName,
                                  @"password": password };

    NSData *postData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:nil];
    NSString *urlString = [DONGU_API_BASE_URL stringByAppendingString:@"/session/"];
    NSData *responseData = [self getDataFromPostRequestWithHeaders:loginHeaders withPostData:postData fromURL:urlString];
    if (responseData)
    {
    responseDict = [self getDictionaryFromResponseData:responseData];
    }
    NSLog(@"%@", @"End of login method reached.");
    return [responseDict objectForKey:@"session-token"];

}

每当调用didReceiveChallenge时,应用程序就会完全冻结。有没有解决的办法?我尝试过使用GCD来调用登录方法,但没有任何乐趣。有没有办法解决这个问题?

1 个答案:

答案 0 :(得分:0)

每次调用该方法时都必须调用提供的完成处理程序,否则连接将不再进一步。如果您不知道如何处理特定挑战,请使用...PerformDefaultHandling进行调用。

此外,请注意,您禁用证书验证的方式非常非常不安全。至少,您应该将提供的公钥与存储在您的应用程序中的已知有效公钥进行比较,并且只有在匹配时才应告知操作系统使用该凭证。否则,您将冒着此代码意外地终止于您的运送应用程序的风险,并失去TLS的所有好处。