Jak korzystać z NSURLConnection, aby połączyć się z SSL dla niezaufanego cert?

Mam następujący prosty kod, aby połączyć się ze stroną SSL

NSMutableURLRequest *urlRequest=[NSMutableURLRequest requestWithURL:url];
[ NSURLConnection sendSynchronousRequest: urlRequest returningResponse: nil error: &error ];

Z tym, że daje błąd, jeśli cert jest własnoręcznie podpisany Error Domain=NSURLErrorDomain Code=-1202 UserInfo=0xd29930 "untrusted server certificate". Czy istnieje sposób, aby ustawić go tak, aby akceptował połączenia (tak jak w przeglądarce można nacisnąć accept) lub sposób, aby go ominąć?

Author: soulshined, 2009-06-01

13 answers

Istnieje obsługiwane API, aby to osiągnąć! Dodaj coś takiego do swojego NSURLConnection delegata:

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
  return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
  if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
    if ([trustedHosts containsObject:challenge.protectionSpace.host])
      [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];

  [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}

Zauważ, że connection:didReceiveAuthenticationChallenge: może wysłać wiadomość do challenge.nadawca (dużo) później, po przedstawieniu użytkownikowi okna dialogowego w razie potrzeby itp.

 409
Author: Gordon Henriksen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-29 06:15:22

Jeśli nie chcesz (lub nie możesz) używać prywatnych interfejsów API, istnieje biblioteka open source (licencja BSD) o nazwie ASIHTTPRequest , która zapewnia owijkę wokół niższego poziomu CFNetwork APIs. Niedawno wprowadzono możliwość zezwalania HTTPS connections na używanie certyfikatów podpisanych samodzielnie lub niezaufanych z API -setValidatesSecureCertificate:. Jeśli nie chcesz ciągnąć całej biblioteki, możesz użyć źródła jako odniesienia do implementacji tej samej funkcjonalności samodzielnie.

 35
Author: Nathan de Vries,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-29 06:15:59

Najlepiej byłoby, gdyby istniały tylko dwa scenariusze, w których aplikacja na iOS musiałaby zaakceptować niezaufany certyfikat.

Scenariusz a: jesteś podłączony do środowiska testowego, które używa certyfikatu z własnym podpisem.

Scenariusz B: Proxy HTTPS ruchu za pomocą MITM Proxy like Burp Suite, Fiddler, OWASP ZAP, etc. Proxy zwrócą certyfikat podpisany przez samo-podpisanego CA, aby proxy był w stanie przechwycić HTTPS ruchu.

Hosty produkcyjne nigdy nie powinny używać zaufanych certyfikatów dla oczywiste powody.

Jeśli symulator iOS musi zaakceptować niezaufany certyfikat do celów testowych, zaleca się, aby nie zmieniać logiki aplikacji w celu wyłączenia wbudowanej walidacji certyfikatu dostarczanej przez interfejsy API NSURLConnection. Jeśli aplikacja zostanie udostępniona publicznie bez usuwania tej logiki, będzie podatna na ataki typu man-in-the-middle.

Zalecanym sposobem przyjmowania zaufanych certyfikatów do celów testowych jest aby zaimportować certyfikat urzędu certyfikacji (CA), który podpisał certyfikat na symulator systemu iOS lub urządzenie z systemem iOS. Napisałem szybki post na blogu, który pokazuje, jak to zrobić, co symulator iOS:

Akceptowanie niezaufanych certyfikatów za pomocą symulatora ios

 32
Author: user890103,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-18 09:21:44

NSURLRequest posiada prywatną metodę o nazwie setAllowsAnyHTTPSCertificate:forHost:, która zrobi dokładnie to, co chcesz. Możesz zdefiniować metodę allowsAnyHTTPSCertificateForHost: na NSURLRequest za pomocą kategorii i ustawić ją na return YES dla hosta, który chcesz nadpisać.

 12
Author: Nathan de Vries,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-01 10:53:41

Aby uzupełnić zaakceptowaną odpowiedź, dla znacznie lepszego bezpieczeństwa, możesz dodać swój certyfikat serwera lub własny certyfikat root CA do keychain ( https://stackoverflow.com/a/9941559/1432048 ), jednak samo zrobienie tego nie spowoduje, że NSURLConnection automatycznie uwierzytelni Twój serwer z podpisem własnym. Nadal musisz dodać poniższy kod do delegata NSURLConnection, jest on skopiowany z przykładowego kodu Apple AdvancedURLConnections i musisz dodać dwa pliki(poświadczenia.h, Poświadczenia.m) od przykładowego kodu apple do Twoich projektów.

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
//        if ([trustedHosts containsObject:challenge.protectionSpace.host])

    OSStatus                err;
    NSURLProtectionSpace *  protectionSpace;
    SecTrustRef             trust;
    SecTrustResultType      trustResult;
    BOOL                    trusted;

    protectionSpace = [challenge protectionSpace];
    assert(protectionSpace != nil);

    trust = [protectionSpace serverTrust];
    assert(trust != NULL);
    err = SecTrustEvaluate(trust, &trustResult);
    trusted = (err == noErr) && ((trustResult == kSecTrustResultProceed) || (trustResult == kSecTrustResultUnspecified));

    // If that fails, apply our certificates as anchors and see if that helps.
    //
    // It's perfectly acceptable to apply all of our certificates to the SecTrust
    // object, and let the SecTrust object sort out the mess.  Of course, this assumes
    // that the user trusts all certificates equally in all situations, which is implicit
    // in our user interface; you could provide a more sophisticated user interface
    // to allow the user to trust certain certificates for certain sites and so on).

    if ( ! trusted ) {
        err = SecTrustSetAnchorCertificates(trust, (CFArrayRef) [Credentials sharedCredentials].certificates);
        if (err == noErr) {
            err = SecTrustEvaluate(trust, &trustResult);
        }
        trusted = (err == noErr) && ((trustResult == kSecTrustResultProceed) || (trustResult == kSecTrustResultUnspecified));
    }
    if(trusted)
        [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}

[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
 10
Author: xiang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:15

Nie mogę brać za to żadnych zasług, ale ten, który znalazłem, bardzo dobrze odpowiadał moim potrzebom. shouldAllowSelfSignedCert jest moją BOOL zmienną. Po prostu dodaj do swojego NSURLConnection delegata i powinieneś być rockin dla szybkiego obejścia na zasadzie jednego połączenia.

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)space {
     if([[space authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust]) {
          if(shouldAllowSelfSignedCert) {
               return YES; // Self-signed cert will be accepted
          } else {
               return NO;  // Self-signed cert will be rejected
          }
          // Note: it doesn't seem to matter what you return for a proper SSL cert
          //       only self-signed certs
     }
     // If no other authentication is required, return NO for everything else
     // Otherwise maybe YES for NSURLAuthenticationMethodDefault and etc.
     return NO;
}
 10
Author: Ryna,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-13 06:12:20

W systemie iOS 9 połączenia SSL nie powiodą się dla wszystkich nieprawidłowych lub podpisanych samodzielnie certyfikatów. Jest to domyślne zachowanie nowej funkcji App Transport Security w systemie iOS 9.0 lub nowszym oraz w systemie OS X 10.11 i nowszym.

Możesz nadpisać to zachowanie w Info.plist, ustawiając NSAllowsArbitraryLoads na YES w słowniku NSAppTransportSecurity. zalecam jednak zastąpienie tego ustawienia wyłącznie w celach testowych.

Tutaj wpisz opis obrazka

Informacje można znaleźć w aplikacji Transport Technote tutaj .

 10
Author: johnnieb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-20 14:36:15

Obejście kategorii opublikowane przez Nathana de Vries przejdzie testy prywatnego API AppStore i jest przydatne w przypadkach, gdy nie masz kontroli nad obiektem NSUrlConnection. Jednym z przykładów jest NSXMLParser, który otworzy podany adres URL, ale nie ujawnia NSURLRequest ani NSURLConnection.

W iOS 4 obejście nadal wydaje się działać, ale tylko na urządzeniu symulator nie wywołuje już metody allowsAnyHTTPSCertificateForHost:.

 6
Author: Alex Suzuki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-16 16:16:47

Musisz użyć NSURLConnectionDelegate, Aby zezwolić na połączenia HTTPS i pojawiają się nowe wywołania zwrotne z iOS8.

Deprecated:

connection:canAuthenticateAgainstProtectionSpace:
connection:didCancelAuthenticationChallenge:
connection:didReceiveAuthenticationChallenge:

Zamiast tych, musisz zadeklarować:

connectionShouldUseCredentialStorage: - wysłane w celu ustalenia, czy ładowarka adresów URL powinna używać magazynu poświadczeń do uwierzytelniania połączenia.

connection:willSendRequestForAuthenticationChallenge: - informuje delegata, że połączenie wyśle prośbę o wyzwanie uwierzytelnienia.

Z willSendRequestForAuthenticationChallenge możesz użyć challenge tak jak z przestarzałymi metodami, na przykład:

// Trusting and not trusting connection to host: Self-signed certificate
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
 5
Author: ricardopereira,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-13 00:46:34

Zamieściłem jakiś kod gist (oparty na cudzej pracy, którą odnotowałem), który pozwala poprawnie uwierzytelnić się przed wygenerowanym przez siebie certyfikatem (i jak uzyskać bezpłatny certyfikat - patrz komentarze na dole Cocoanetics)

Mój kod jest tutaj github

 2
Author: David H,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-16 23:25:34

Jeśli chcesz nadal używać sendSynchronousRequest pracuję w tym rozwiązaniu:

FailCertificateDelegate *fcd=[[FailCertificateDelegate alloc] init];

NSURLConnection *c=[[NSURLConnection alloc] initWithRequest:request delegate:fcd startImmediately:NO];
[c setDelegateQueue:[[NSOperationQueue alloc] init]];
[c start];    
NSData *d=[fcd getData];

Możesz go zobaczyć tutaj: Objective - C SSL Synchronous Connection

 2
Author: jgorozco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:05

Z AFNetworking z powodzeniem wykorzystałem https webservice z poniższym kodem,

NSString *aStrServerUrl = WS_URL;

// Initialize AFHTTPRequestOperationManager...
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];

[manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
manager.securityPolicy.allowInvalidCertificates = YES; 
[manager POST:aStrServerUrl parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject)
{
    successBlock(operation, responseObject);

} failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
    errorBlock(operation, error);
}];
 0
Author: cjd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-07 09:37:55

Możesz użyć tego kodu

-(void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
     if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodServerTrust)
     {
         [[challenge sender] useCredential:[NSURLCredential credentialForTrust:[[challenge protectionSpace] serverTrust]] forAuthenticationChallenge:challenge];
     }
}

Użyj -connection:willSendRequestForAuthenticationChallenge: zamiast tych przestarzałych metod

Deprecated:

-(BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace  
-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 
-(void)connection:(NSURLConnection *)connection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
 0
Author: Vaibhav Sharma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-07 12:31:23