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

Bardzo, bardzo frustrujące! Od tego czasu ciągnę za włosy moje. Używam samopodpisanego certyfikatu na moim serwerze Linode. Port ma 8000, nie można go uruchomić na 443. Nie sądzę jednak, że to jest powód. Oto mój kod, to jest 99% boilerplate:Żądania iOS 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]; 

Na dole:

#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]]); 
} 

OMG POMOC!

UPDATE

on pracował z tej metody delegata. Otrzymuję odpowiedź, ale jest problem.

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { 
    [[challenge sender] useCredential:[NSURLCredential 
             credentialWithUser:@"user" 
             password:@"password" 
             persistence:NSURLCredentialPersistencePermanent] forAuthenticationChallenge:challenge]; 

} 

Podane przeze mnie "użytkownik" i "hasło są całkowicie losowe i nie są sprawdzane przez serwer. Jak mogę sprawdzić dane uwierzytelniające przed zaakceptowaniem połączenia na moim serwerze?

EDIT: Używam serwera node.js

+0

„«użytkownik»i«hasło», które mam pod warunkiem są całkowicie przypadkowe i nie są sprawdzane przez serwer” - to już zupełnie inna kwestia. Powinieneś zadać to jako osobne pytanie i być może powrócić do tego pytania. Konfiguracja Linode może być nietypowa, więc możesz przejść do Super User lub Server Fault. (I prawdopodobnie powinieneś zaakceptować odpowiedź Fonix, ponieważ wydaje się, że pomogła ci rozwiązać problem). – jww

Odpowiedz

2

nie wiem, czy będzie to rzeczywiście rozwiązać ten problem, ale może pomóc. powinieneś używać

– connection:willSendRequestForAuthenticationChallenge: 

, ponieważ inne metody są przestarzałe. spojrzeć na przegląd NSURLConnectionDelegate protocol

+0

Prawie zadziałało, zobacz moje zaktualizowane pytanie –

+0

Niestety jestem trochę noob z tym uwierzytelniania rzeczy, więc nie jestem pewien – Fonix

8

Pierwsze odpowiedni opis błędu może pomóc:

Więc pierwsza domena błąd kCFStreamErrorDomainSSL oznacza, że ​​kod błędu jest wyświetlany kod błędu SSL, jak określono w Bezpieczeństwa/SecureTransport.h :

kCFStreamErrorDomainSSL, -9813 oznacza:

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

A to oznacza po prostu, nie masz zaufanego certyfikatu głównego i Conne ction nie działa z powodu tej nieudanej autoryzacji.

Podaj certyfikat główny na urządzeniu do uwierzytelniania zaufania serwera i wszystko jest w porządku.

Istnieje kilka podejść do wdrożenia uwierzytelniania zaufania serwera z samopodpisanymi certyfikatami, jeden bardziej bezpieczny niż drugi.

Najprostsze podejście wymaga samopodpisanego certyfikatu, który jest przechowywany w pakiecie aplikacji, a następnie pobierany i porównywany bajtowo. Oto przykład:

Implementing server trust authentication with a self-signed certificate.

Należy również przeczytać: Technical Note TN2232 HTTPS Server Trust Evaluation i Technical Q&A QA1360 Describing the kSecTrustResultUnspecified error.

Bardziej preferowanym podejściem jest użycie urzędu certyfikacji (CA), którym możesz być sam. Oznacza to, że tworzysz własny urząd certyfikacji i certyfikaty podpisane przy użyciu tego urzędu certyfikacji.

Kroki są podobne:

  1. Bundel plik DER swojego certyfikatu głównego CA w swojej aplikacji.
  2. Uchwyt uwierzytelniania zaufania serwera następująco:

    1. dostać wyzwanie uwierzytelnienia
    2. odebrania obiektu zaufanie wyzwanie
    3. utworzyć obiekt zaświadczenie z danymi w wiązce
    4. ustaw obiekt certyfikatu jako kotwicę do obiektu zaufania za pomocą funkcji SecTrustSetAnchorCertificates.
    5. ocenić zaufanie
+4

Oto adres URL do odszyfrowania innych kodów błędów ... http://www.opensource.apple.com/ source/libsecurity_ssl/libsecurity_ssl-36800/lib/SecureTransport.h – cat

Powiązane problemy