Игнорирование ошибок сертификата с NSURLConnection - PullRequest
18 голосов
/ 22 сентября 2010

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

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.

Ответы [ 6 ]

17 голосов
/ 22 сентября 2010

Вы можете просто проигнорировать недействительный сертификат, если вы не отправляете конфиденциальную информацию. Эта статья описывает, как вы могли бы сделать это. Вот пример реализации 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]];
16 голосов
/ 28 августа 2014

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

- (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];
5 голосов
/ 26 сентября 2014

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

-(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 { ... }
3 голосов
/ 06 августа 2014

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

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

Также, возможно, вы захотите взглянуть на техническую записку Apple TN2232: оценка доверия сервера HTTPS kSecTrustResultUnspecified - успех, см. Технические вопросы и ответы 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];
}
3 голосов
/ 18 декабря 2012

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

Реализовать это:

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

Делая это:

[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];

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

1 голос
/ 22 сентября 2010

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

...