2013-08-03 5 views
14
NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813) 

Très, très frustrant! Je me suis tiré les cheveux pendant des heures avec ça. J'utilise un certificat auto-signé sur mon serveur Linode. Le port est 8000, n'a pas pu le faire fonctionner sur 443. Je ne crois pas que ce soit la raison cependant. Voici mon code, il est 99% boilerplate:iOS demandes HTTPS 101

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.myserver.com:8000/test.json"]]; 
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES]; 

Au fond:

#pragma mark NSURLConnectionDelegate 

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace { 
    NSLog(@"protectionSpace: %@", [protectionSpace authenticationMethod]); 

    // We only know how to handle NTLM authentication. 
    if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodNTLM]) 
     return YES; 

    // Explicitly reject ServerTrust. This is occasionally sent by IIS. 
    if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust]) 
     return NO; 

    return NO; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { 
    [[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge]; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 
    NSLog(@"%@", response); 
} 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 
    NSLog(@"%@", data); 
} 

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 
    NSLog(@"didFailWithError"); 
    NSLog([NSString stringWithFormat:@"Connection failed: %@", [error description]]); 
} 

AIDE OMG!

MISE À JOUR

Il a collaboré avec cette méthode de délégué. Je reçois la réponse, mais il y a un problème. Les mots "user" et "password" que j'ai fournis sont complètement aléatoires et ne sont pas vérifiés par le serveur. Comment puis-je vérifier les informations d'identification avant d'accepter la connexion sur mon serveur?

EDIT: Je suis en cours d'exécution d'un serveur Node.js

+0

« Le « utilisateur » et « mot de passe » que j'ai fourni sont complètement aléatoires et ne sont pas vérifiées par le serveur » - c'est une autre question. Vous devriez le poser comme une question distincte et peut-être revenir à cette question. La configuration de Linode peut être hors sujet, vous devrez peut-être passer à Super User ou Server Fault. (Et vous devriez probablement accepter la réponse de Fonix puisqu'elle semble vous avoir aidé à résoudre le problème). – jww

Répondre

2

ne sais pas si cela va réellement résoudre le problème, mais il peut aider. vous devriez utiliser

– connection:willSendRequestForAuthenticationChallenge: 

puisque les autres méthodes sont déconseillés. jetez un oeil à la vue d'ensemble de la NSURLConnectionDelegate protocol

+0

Presque travaillé, voir ma question mise à jour –

+0

malheureusement im un peu d'un noob avec cette substance d'authentification, donc je ne suis pas sûr – Fonix

8

Obtenir la description d'erreur correspondant peut aider:

Alors, d'abord le domaine d'erreur kCFStreamErrorDomainSSL signifie que le code d'erreur est un code d'erreur SSL tel que défini dans la sécurité/SecureTransport.h :

kCFStreamErrorDomainSSL, -9813 signifie:

errSSLNoRootCert = -9813, /* cert chain not verified by root */

et cela signifie simplement, vous avez pas de certificat racine de confiance et Conne La défaillance échoue à cause de cet échec d'authentification.

Fournissez un certificat racine sur le périphérique pour l'authentification de confiance du serveur et tout va bien.

Il existe plusieurs approches pour implémenter l'authentification d'approbation de serveur avec des certificats auto-signés, l'un plus sécurisé que l'autre.

L'approche la plus simple nécessite un certificat auto-signé qui est stocké dans l'ensemble de l'application, puis récupéré et simplement comparé par octet. Voici un exemple:

Implementing server trust authentication with a self-signed certificate.

Il s'agit d'une lecture obligatoire: Technical Note TN2232 HTTPS Server Trust Evaluation et Technical Q&A QA1360 Describing the kSecTrustResultUnspecified error.

L'approche la plus préférée consiste à utiliser une autorité de certification (CA) que vous pouvez être vous-même. Autrement dit, vous créez votre propre autorité de certification et vos certificats signés avec cette autorité de certification.

Les étapes sont similaires:

  1. Bundel le fichier DER de votre certificat racine de CA dans votre application.
  2. Manipulez l'authentification de confiance du serveur comme suit:

    1. obtenir le défi d'authentification
    2. récupérer l'objet de la confiance du défi
    3. créer un objet de certificat à partir des données dans votre paquet
    4. régler la objet de certificat en tant qu'ancre à l'objet de confiance à l'aide de la fonction SecTrustSetAnchorCertificates.
    5. évaluer la confiance
+4

Voici l'URL pour décrypter d'autres codes d'erreur ... http://www.opensource.apple.com/ source/libsecurity_ssl/libsecurity_ssl-36800/lib/SecureTransport.h – cat