Я работаю над iOS 8+ App, которое должно позволить пользователям общаться с WebService на своих серверах. Разумеется, использование HTTPS-соединения было бы оптимальным для этого, но на самом деле будет много пользователей, которые не имеют (доверенного) SSL-сертификата на своем сервере.NSURLSession - Игнорировать предупреждение сертификата SSL
Я хотел бы разрешить пользователям самостоятельно решать, хотят ли они использовать простой HTTP или HTTPS. Кроме того, HTTPS должен работать, даже если сервер имеет действующий SSL-сертификат. Так как сертификат «только» гарантирует подлинность сервера, но не имеет никакого влияния на шифрование соединения это сам, untrustes HTTPS подоконник имеет свои преимущества по сравнению с обычной HTTP:
- Я знаю, что сертификаты были изобретены хорошая причина
- Я знаю о рисках MITM атаки
- Я согласен, что с помощью действительного сертификата SSL будет лучшим вариантом
- Я все еще верю, что с помощью HTTPS без CERT должна быть вариантом для пользователей ,
Итак, как это сделать?
Сначала я работал с 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