使用NSURLConnection忽略证书错误

时间:2010-09-22 06:16:16

标签: cocoa-touch cocoa 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];

然后我在didReceiveResponse方法中获得了EXC_BAD_ACCESS。

6 个答案:

答案 0 :(得分:17)

如果您没有发送任何敏感信息,则可以忽略无效证书。 This article描述了如何做到这一点。以下是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]];

答案 1 :(得分:16)

使用新的正确(非弃用,非私人)方式:

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

答案 2 :(得分:5)

我有类似的问题。通过使用下面的代码片段来解决它:

-(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 :(得分:3)

您已将委托设置为self,因此您可以通过在发送该请求的类中实现NSURLConnectionDelegate的一部分来解决此问题。

实施这个:

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

通过这样做:

[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];

注意:这不是在生产中使用的解决方案。证书存在是有原因的! :)

答案 4 :(得分:3)

这不符合您的“如何忽略错误”的问题。这是不负责任的。

相反,它向您展示了如何加载证明服务器的CA,以便连接可以按预期进行。下面,CA与应用程序捆绑在一起,称为ca-cert.der。它是DER(而不是PEM)编码的证书。

另外,您可能想看一下Apple的Technical Note TN2232 HTTPS Server Trust EvaluationkSecTrustResultUnspecified成功,请参阅Technical Q&A QA1360 Describing the kSecTrustResultUnspecified error

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

答案 5 :(得分:1)

您使用的是HTTPS网址吗?如果是这样,请转到浏览器中的URL并检查证书。确保证书对您尝试使用的域或子域有效,并且已在服务器上安装了所有中间证书。我遇到了与此类似的问题,解决方案是安装中间证书。