Ignorando erros de certificado com NSURLConnection

Estou recebendo este erro

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." 

Eu estou usando esse método:

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

Como posso consertar isso?

Eu tentei este código:

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

mas depois eu obtenho o EXC_BAD_ACCESS no método didReceiveResponse.

Você pode simplesmente ignorar o certificado inválido se não estiver enviando nenhuma informação confidencial. Este artigo descreve como você pode fazer isso. Aqui está um exemplo de implementação por Alexandre Colucci para um dos methods descritos nesse artigo.

Essencialmente, você quer definir uma interface fictícia logo acima da @implementation :

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

E antes de chamar sendSynchronousRequest , invoque o método privado que você definiu na interface fictícia:

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

O caminho correto (não obsoleto, não privado) usando o novo:

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

método que apple especificou deve ser usado para NSURLConnectionDelegates é responder ao método ServerTrust com a credencial que foi fornecida para o espaço de proteção (isso permitirá que você conecte:

 - (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... } 

Este método é chamado várias vezes uma vez para cada método de autenticação disponível, se você não quiser logar usando esse método use:

  [challenge.sender rejectProtectionSpaceAndContinueWithChallenge:challenge]; 

Eu tive problema semelhante. Resolvido usando o trecho de código abaixo:

 -(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]; } } 

Como os methods abaixo são obsoletos:

 - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)space { ... } - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { ... } 

Você definiu o delegado como autônomo, portanto, pode corrigir isso implementando parte de NSURLConnectionDelegate na class que envia essa solicitação.

Implemente isso:

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

Fazendo isto:

 [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge]; 

Nota: esta não é uma solução para usar na produção. Certificados existem por um motivo! 🙂

Isso não responde à sua pergunta “como ignorar erros”. Isso é ser irresponsável.

Em vez disso, mostra como carregar a CA que certifica o servidor para que a conexão possa prosseguir conforme o esperado. Abaixo, a CA é empacotada com o aplicativo e é chamada ca-cert.der . É um certificado codificado DER (em oposição ao PEM).

Além disso, você pode querer dar uma olhada na Avaliação de Confiança de Servidor HTTPS da Nota Técnica TN2232 da Apple. kSecTrustResultUnspecified é sucesso, consulte Q & A técnico QA1360 Descrição do erro 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]; } 

Você está usando uma URL HTTPS. Se assim for, vá para o url em um navegador e verifique o certificado. Verifique se o certificado é válido para o domínio ou subdomínio que você está tentando usar e se todos os certificados intermediários foram instalados em seu servidor. Eu tive um problema semelhante a este, e a solução foi instalar os certificados intermediários.