【问题标题】:Ignoring certificate errors with NSURLConnection使用 NSURLConnection 忽略证书错误
【发布时间】:2023-03-23 09:25:01
【问题描述】:

我收到这个错误

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。

【问题讨论】:

  • “使用 NSURLConnection 忽略证书错误” - 最好解决问题而不是忽略错误。如果您不打算正确使用 PKI 和 SSL,那为什么还要使用它呢?

标签: cocoa-touch cocoa nsurlconnection


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    如果您不发送任何敏感信息,您可以简单地忽略无效证书。 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]];
    

    【讨论】:

    • 此链接使用私有 api,使用它我的应用会被苹果拒绝吗?如果是这样,那么我不能使用它,因为我必须将我的应用程序放在 appstore 上。还有其他方法吗?
    • 我认为这篇文章准确地回答了你的问题:stackoverflow.com/questions/933331/…
    • 不,这不起作用 didRecieveResponse 在 canAuthenticateAgainstProtectionSpace 方法及其在 didRecieveResponse 方法中崩溃之前首先被调用。
    • 这已在苹果文档中说明。检查这个:developer.apple.com/library/ios/technotes/tn2232/_index.html介绍部分
    • 很好的答案,与sendSynchronousRequest: 完美配合。显然应该只在测试/调试时使用(显然任何生产服务器都应该有适当的 SSL 证书开始),使用一对 #ifdef DEBUG 块很容易完成。
    【解决方案3】:

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

    实现这个:

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

    通过这样做:

    [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
    

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

    【讨论】:

      【解决方案4】:

      这并不能回答您“如何忽略错误”的问题。这是不负责任的。

      相反,它向您展示了如何加载验证服务器的 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];
      }
      

      【讨论】:

      • 很好的参考和例子。这是newer documentation,它描述了使用较新的 URLSessionDelegate 方法。
      【解决方案5】:

      使用新方法的正确(非弃用、非私有)方式:

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

      苹果指定的用于 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];
      

      【讨论】:

        【解决方案6】:

        我有类似的问题。通过使用下面的代码 sn-p 解决了它:

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

        【讨论】:

        • 这很好,但它不处理CA that's not preloaded 或用户添加到商店。但是使用预加载的 CA 列表是危险的,因为 CA Zoo 中的任何 CA 都可以声称对站点进行认证(即使是错误的,例如为拦截颁发证书的那些)。我认为最好指定应该对站点进行认证的 CA,这样糟糕的 CA 就不会破坏通道。
        猜你喜欢
        • 1970-01-01
        • 2023-03-31
        • 2012-08-17
        • 2012-05-02
        • 2019-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多