Игнорирование ошибок сертификата с помощью NSURLConnection

Я получаю эту ошибку

The certificate for this server is invalid. You might be connecting to a server
that is pretending to be "server addres goes here" which could put your
confidential information at risk."

Я использую этот метод:

[NSURLConnection sendSynchronousRequest:request
                      returningResponse:&response
                                  error:&error];

Как я могу это исправить?

Я пробовал этот код:

 NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request
                                                               delegate:self];

но затем я получаю EXC_BAD_ACCESS в методе didReceiveResponse.

Ответ 1

Вы можете просто игнорировать недействительный сертификат, если вы не отправляете какую-либо конфиденциальную информацию. В этой статье описывается, как вы могли это сделать. Ниже приведен пример реализации Alexandre Colucci для одного из методов, описанных в этой статье.

По существу, вы хотите определить фиктивный интерфейс чуть выше @implementation:

@interface NSURLRequest (DummyInterface)
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host;
+ (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)host;
@end

И прежде чем вы вызовете sendSynchronousRequest, вызовите частный метод, который вы определили в фиктивном интерфейсе:

[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[URL host]];

Ответ 2

Правильный (не устаревший, не закрытый) способ с использованием нового:

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge

который указанный apple должен использовать для NSURLConnectionDelegates, должен отвечать на метод ServerTrust учетными данными, предоставленными для защитного места (это позволит вам подключиться:

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
    {
        NSLog(@"Ignoring SSL");
        SecTrustRef trust = challenge.protectionSpace.serverTrust;
        NSURLCredential *cred;
        cred = [NSURLCredential credentialForTrust:trust];
        [challenge.sender useCredential:cred forAuthenticationChallenge:challenge];
        return;
    }

    // Provide your regular login credential if needed...
}

Этот метод вызывается несколько раз один раз для каждого доступного метода проверки подлинности, если вы не хотите использовать этот метод используя этот метод:

 [challenge.sender rejectProtectionSpaceAndContinueWithChallenge:challenge];

Ответ 3

У меня была аналогичная проблема. Чтобы решить эту проблему, используйте ниже фрагмент кода:

-(void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {

    NSLog(@"This will execute successfully!");
    if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodServerTrust) {

        [[challenge sender] useCredential:[NSURLCredential credentialForTrust:[[challenge protectionSpace] serverTrust]] forAuthenticationChallenge:challenge];
    }
}

Поскольку ниже методы устарели:

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)space { ... }

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { ... }

Ответ 4

Вы установили делегат как self, поэтому вы можете исправить это, выполнив часть NSURLConnectionDelegate в классе, отправляющем этот запрос.

Внедрите это:

-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;

Сделав это:

[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];

Примечание: это НЕ решение для использования в производстве. Сертификаты существуют по какой-то причине!:)

Ответ 5

Используете ли вы URL-адрес HTTPS. Если так, перейдите к URL-адресу в браузере и проверьте сертификат. Убедитесь, что сертификат действителен для домена или поддомена, который вы пытаетесь использовать, и чтобы все промежуточные сертификаты были установлены на вашем сервере. У меня была проблема, подобная этой, и решение заключалось в установке промежуточных сертификатов.

Ответ 6

Это не отвечает на ваш вопрос "как игнорировать ошибки". Это безответственно.

Скорее, он показывает вам, как загрузить ЦС, который сертифицирует сервер, чтобы соединение могло продолжаться, как ожидалось. Ниже CA поставляется вместе с приложением и называется ca-cert.der. Его сертификат DER (в отличие от PEM) закодирован.

Кроме того, вы можете посмотреть на Apple Техническая нота TN2232 HTTPS Server Trust Evaluation. kSecTrustResultUnspecified является успешным, см. Техническое Q & A QA1360 Описание ошибки kSecTrustResultUnspecified.

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

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:
(NSURLAuthenticationChallenge *)challenge
{        
    if ([[[challenge protectionSpace] authenticationMethod] isEqualToString: NSURLAuthenticationMethodServerTrust])
    {
        do
        {
            SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
            NSCAssert(serverTrust != nil, @"serverTrust is nil");
            if(nil == serverTrust)
                break; /* failed */

            NSData* caCert = [NSData dataWithContentsOfFile:@"ca-cert.der"];
            NSCAssert(caCert != nil, @"caCert is nil");
            if(nil == caCert)
                break; /* failed */

            SecCertificateRef caRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)caCert);
            NSCAssert(caRef != nil, @"caRef is nil");
            if(nil == caRef)
                break; /* failed */

            NSArray* caArray = [NSArray arrayWithObject:(__bridge id)(caRef)];
            NSCAssert(caArray != nil, @"caArray is nil");
            if(nil == caArray)
                break; /* failed */

            OSStatus status = SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)caArray);
            NSCAssert(errSecSuccess == status, @"SecTrustSetAnchorCertificates failed");
            if(!(errSecSuccess == status))
                break; /* failed */

            SecTrustResultType result = -1;
            status = SecTrustEvaluate(serverTrust, &result);
            if(!(errSecSuccess == status))
                break; /* failed */

            NSLog(@"Result: %d", result);

            /* This test looks for a "SUCCESS" */
            /* kSecTrustResultUnspecified and kSecTrustResultProceed are success */
            if(result != kSecTrustResultUnspecified && result != kSecTrustResultProceed)
                break; /* failed */

#if 0
            /* Alternate test looks for a "NOT FAILURE" */
            /* Treat kSecTrustResultConfirm and kSecTrustResultRecoverableTrustFailure as success */
            /*   since the user will likely tap-through to see the dancing bunnies */
            if(result == kSecTrustResultDeny || result == kSecTrustResultFatalTrustFailure || result == kSecTrustResultOtherError)
                break; /* failed to trust cert (good in this case) */
#endif

            // The only good exit point
            return [[challenge sender] useCredential: [NSURLCredential credentialForTrust: serverTrust]
                          forAuthenticationChallenge: challenge];

        } while(0);
    }

    // Bad dog
    return [[challenge sender] cancelAuthenticationChallenge: challenge];
}