iOS / Cocoa - NSURLSession - Gestion de l'autorisation HTTPS de base

[édité pour fournir plus d'informations]

(Je ne suis pas en utilisant AFNetworking pour ce projet. Je peut le faire à l'avenir, mais pour résoudre ce problème/incompréhension de la première.)

DE CONFIGURATION DU SERVEUR D'

Je ne peux pas en mesure de fournir les services proposés ici, mais c'est un simple service fiable et qui renvoie XML selon une URL de la forme:

https://username:[email protected]/webservice

Je veux me connecter à l'URL en HTTPS à l'aide de GET, et à déterminer les échecs d'authentification (code d'état http 401).

J'ai confirmé que le service web est disponible, et que je peux avec succès (avec un code d'état http 200) saisir XML à partir de l'url spécifié à l'aide d'un nom d'utilisateur et mot de passe. Je l'ai fait avec un navigateur web, et avec AFNetworking 2.0.3, et en utilisant NSURLConnection.

J'ai également confirmé que je suis en utilisant les informations d'identification correctes à toutes les étapes.

Donné les bonnes informations d'identification et le code suivant:

//Note: NO delegate provided here.
self.sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
self.session = [NSURLSession sessionWithConfiguration:self.sessionConfig
                                  delegate:nil
                             delegateQueue:nil];

NSURLSessionDataTask *dataTask = [self.session dataTaskWithURL:self.requestURL     completionHandler: ...

Le code ci-dessus va travailler. Il va réussir à se connecter au serveur, obtenir un code d'état http 200, et de renvoyer les données (XML).

PROBLÈME 1

Cette simple approche échoue dans les cas où les informations ne sont pas valides. Dans ce cas, l'achèvement de bloc n'est jamais appelé, pas de code d'état (401) est fourni, et finalement, le temps de travail.

TENTATIVE DE SOLUTION

J'ai affecté un délégué à la NSURLSession, et je suis de la manipulation de l'rappels suivants:

-(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
    if (_sessionFailureCount == 0) {
        NSURLCredential *cred = [NSURLCredential credentialWithUser:self.userName password:self.password persistence:NSURLCredentialPersistenceNone];        
    completionHandler(NSURLSessionAuthChallengeUseCredential, cred);
    } else {
        completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
    }
    _sessionFailureCount++;
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition,    NSURLCredential *credential))completionHandler
{
    if (_taskFailureCount == 0) {
        NSURLCredential *cred = [NSURLCredential credentialWithUser:self.userName password:self.password persistence:NSURLCredentialPersistenceNone];        
        completionHandler(NSURLSessionAuthChallengeUseCredential, cred);
    } else {
        completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
    }
    _taskFailureCount++;
}

PROBLÈME 1 LORS DE L'UTILISATION DE LA TENTATIVE DE SOLUTION

Veuillez noter que l'utilisation de ivars _sessionFailureCount et _taskFailureCount. Je suis à l'aide de ces car le défi de l'objet @previousFailureCount propriété n'est jamais avancé! Elle reste toujours à zéro, peu importe combien de fois ces méthodes de rappel sont appelés.

PROBLÈME 2 LORS DE L'UTILISATION DE LA TENTATIVE DE SOLUTION

En dépit de l'utilisation des informations d'identification correctes (comme le prouve la réussite de leur utilisation avec un nul de son délégué), l'authentification échoue.

Les rappels suivants se produisent:

URLSession:didReceiveChallenge:completionHandler:
(challenge @ previousFailureCount reports as zero)
(_sessionFailureCount reports as zero)
(completion handler is called with correct credentials)
(there is no challenge @error provided)
(there is no challenge @failureResponse provided)


URLSession:didReceiveChallenge:completionHandler:
(challenge @ previousFailureCount reports as **zero**!!)
(_sessionFailureCount reports as one)
(completion handler is called with request to cancel challenge)
(there is no challenge @error provided)
(there is no challenge @failureResponse provided)

//Finally, the Data Task's completion handler is then called on us.
(the http status code is reported as zero)
(the NSError is reported as NSURLErrorDomain Code=-999 "cancelled")

(Le NSError fournit également un NSErrorFailingURLKey, qui me montre que l'URL et les informations d'identification sont correctes.)

Toutes les suggestions sont les bienvenues!

source d'informationauteur Womble