我的工作在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这应该工作,不应该吗?
是的,因为在当今世界,安全是无关紧要的,对吗?做这样的事情只会让问题变得更糟,这是一个好主意吗?攻击者只是寻找一个弱点,他们不关心其他部分的安全性。而且安全性不佳总是有借口。 – zaph
这是您的意见,与问题无关。如果有人有服务器但没有SSL证书,他将被迫使用纯HTTP。没有认证和没有完整性/加密。与没有证书的HTTPS(没有验证,但仍然是加密)相比,这种情况究竟如何严重?许多NAS盒可以与HTTPS一起使用,但没有(可信)证书。为什么不能在这些情况下使用HTTPS? –
的确,我认为安全应该是一项要求,如果存在的话应该是真实的。如果没有证书HTTPS是不可能的,则它是来自用于加密对称加密密钥的证书的公钥。如果没有可信任的证书并且没有固定,那么只会出现安全性,并且比没有安全性更糟糕,那就是用户信任不应该信任的内容。这些日子的攻击非常复杂,而且攻击者很容易应用。 – zaph