2015-11-23 160 views
0

我的工作在iOS 8+应用程序应该允许用户与的WebService自己的服务器上沟通。当然,使用HTTPS连接最好实践这一点,但实际上会有很多用户在其服务器上没有(可信赖的)SSL证书。NSURLSession - 忽略SSL证书警告

我想让用户自己决定是否使用纯HTTP或HTTPS。 此外,即使服务器现在有有效的SSL证书,HTTPS也应该可以工作。由于证书“只是”保证了服务器的身份,但对连接它自身的加密没有影响,untrustes HTTPS梁具有其通过纯HTTP优点:

  • 我知道证书已发明了一个很好的理由
  • 我知道中间人的风险攻击
  • 我同意使用有效的SSL证书将是最好的选择
  • 我仍然相信,使用HTTPS没有证书应该是用户的选择。

那么,如何才能做到这一点?

首先,我与NSURLConnection sendAsynchronousRequest合作,但由于这不允许任何控制关于证书检查过程(因为它在iOS 9中已弃用)我切换到NSURLSession。

我跟着Apples docs信任我的服务器,但没有成功:

- (id)init { 
    ... 
    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; 
    session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]]; 
    ... 
} 


- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {  
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { 
     SecTrustRef trust = challenge.protectionSpace.serverTrust; 
     NSURLCredential *credential = [NSURLCredential credentialForTrust:trust]; 
     completionHandler(NSURLSessionAuthChallengeUseCredential, credential); 
    } else { 
     completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); 
    } 
} 

- (void)sendRequest:(NSURL *)URL { 
    NSURLRequest* request = [[NSURLRequest alloc] initWithURL:url]; 

    [[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
     if (error) { 
      // ERROR 
      --> Log error 
     } else { 
      // SUCCESS 
     } 
    }] resume]; 
} 

- (void)test { 
    // HTTP works fine 
    [self sendRequest:[NSURL URLWithString:@"http://my.test.page.xy"]]; 

    // Error with HTTPS 
    [self sendRequest:[NSURL URLWithString:@"https://my.test.page.xy"]]; 

    // Error Domain=NSURLErrorDomain 
    // Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." 
    // UserInfo={ 
    //  _kCFStreamErrorCodeKey=-9824, 
    //  NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, 
    //  NSUnderlyingError= { 
    //   Error Domain=kCFErrorDomainCFNetwork 
    //   Code=-1200 
    //   UserInfo={ 
    //    _kCFStreamPropertySSLClientCertificateState=0, 
    //    _kCFNetworkCFStreamSSLErrorOriginalValue=-9824, 
    //    _kCFStreamErrorDomainKey=3, 
    //    _kCFStreamErrorCodeKey=-9824 
    //   } 
    //  }, 
    //  NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., 
    //  NSErrorFailingURLKey=https://my.test.page.xy, 
    //  NSErrorFailingURLStringKey=https://my.test.page.xy, 
    //  _kCFStreamErrorDomainKey=3 
    // } 
} 

无论我处理URLSession:session task:didReceiveChallenge:challenge completionHandler:与否没什么区别。错误是一样的。

那么,任何想法如何在没有证书的服务器上使用HTTPS?根据Apples docs这应该工作,不应该吗?

+0

是的,因为在当今世界,安全是无关紧要的,对吗?做这样的事情只会让问题变得更糟,这是一个好主意吗?攻击者只是寻找一个弱点,他们不关心其他部分的安全性。而且安全性不佳总是有借口。 – zaph

+1

这是您的意见,与问题无关。如果有人有服务器但没有SSL证书,他将被迫使用纯HTTP。没有认证和没有完整性/加密。与没有证书的HTTPS(没有验证,但仍然是加密)相比,这种情况究竟如何严重?许多NAS盒可以与HTTPS一起使用,但没有(可信)证书。为什么不能在这些情况下使用HTTPS? –

+0

的确,我认为安全应该是一项要求,如果存在的话应该是真实的。如果没有证书HTTPS是不可能的,则它是来自用于加密对称加密密钥的证书的公钥。如果没有可信任的证书并且没有固定,那么只会出现安全性,并且比没有安全性更糟糕,那就是用户信任不应该信任的内容。这些日子的攻击非常复杂,而且攻击者很容易应用。 – zaph

回答

0

我认为你必须实际评估的信任对象一次(尽管这评价的实际结果被忽略)。

随着中说,检查,以确保它实际上证书是你接受它。有关如何执行此操作的示例,请参见Overriding SSL Chain Validation Correctly