Запросы iOS HTTPS 101
NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)
Очень, очень расстраиваю! Я так долго тянул за волосы. Я использую самозаверяющий сертификат на моем сервере Linode. Порт 8000, не мог заставить его работать на 443. Я не верю, что это причина. Здесь мой код, это 99% -ный шаблон:
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.myserver.com:8000/test.json"]];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
Внизу:
#pragma mark NSURLConnectionDelegate
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
NSLog(@"protectionSpace: %@", [protectionSpace authenticationMethod]);
// We only know how to handle NTLM authentication.
if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodNTLM])
return YES;
// Explicitly reject ServerTrust. This is occasionally sent by IIS.
if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust])
return NO;
return NO;
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
[[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(@"%@", response);
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSLog(@"%@", data);
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(@"didFailWithError");
NSLog([NSString stringWithFormat:@"Connection failed: %@", [error description]]);
}
OMG HELP!
UPDATE
Он работал с этим методом делегата. Я получаю ответ, но есть проблема.
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
[[challenge sender] useCredential:[NSURLCredential
credentialWithUser:@"user"
password:@"password"
persistence:NSURLCredentialPersistencePermanent] forAuthenticationChallenge:challenge];
}
"Пользователь" и "пароль", которые я предоставил, полностью случайны и не проверяются сервером. Как проверить учетные данные, прежде чем принимать подключение на моем сервере?
EDIT: я запускаю сервер Node.js
Ответы
Ответ 1
Получение соответствующего описания ошибки может помочь:
Итак, сначала область ошибок kCFStreamErrorDomainSSL
означает, что код ошибки является кодом ошибки SSL, как определено в Security/SecureTransport.h:
kCFStreamErrorDomainSSL, -9813 означает:
errSSLNoRootCert = -9813, /* cert chain not verified by root */
И это просто означает, что у вас нет доверенного корневого сертификата, и соединение выходит из строя из-за этого сбоя проверки подлинности.
Предоставьте корневой сертификат устройства для проверки подлинности доверия сервера, и вы в порядке.
Существует несколько подходов к реализации аутентификации доверия сервера с самозаверяющими сертификатами, более безопасными, чем другие.
Простейший подход требует наличия самозаверяющего сертификата, который хранится в комплекте приложения, затем извлекается и просто сравнивается по байтам. Вот пример:
Реализация аутентификации доверия сервера с самозаверяющим сертификатом.
Это также необходимо прочитать: Техническая нота TN2232
HTTPS Server Trust Evaluation и Техническое Q & A QA1360 Описание ошибки kSecTrustResultUnspecified.
Более предпочтительным подходом является использование центра сертификации (CA), которым вы можете быть самим собой. То есть вы создаете свой собственный ЦС и сертификаты, подписанные с этим ЦС.
Шаги аналогичны:
Ответ 2
не уверен, что это действительно устранит проблему, но может помочь. вы должны использовать
– connection:willSendRequestForAuthenticationChallenge:
поскольку другие методы устарели. ознакомьтесь с обзором протокола NSURLConnectionDelegate