Проблемы с SSL-закреплением и AFNetworking 2.5.0 (ошибка NSURLErrorDomain -1012.)

нам было трудно защитить сетевые подключения нашего приложения с помощью SSL с помощью AFNetworking 2.5.0.

мы используем самозаверяющий центр сертификации и реализовали пользовательскую политику безопасности с использованием закрепленных сертификатов.

мы протестировали довольно много конфигураций, предоставляемых AFNetworking, но пока не повезло. Сообщение об ошибке, которое мы получаем:

2015-01-05 19: 03: 07.191 AppName[9301: 319051] ошибка обновления пользователя путешествие. Ошибка: Ошибка Domain=NSURLErrorDomain Код=-1012 "На операция не может быть завершена. (Ошибка NSURLErrorDomain -1012.)" UserInfo=0x7ae056b0 {NSErrorFailingURLKey=https://api.XXX.com/XXX/XXX/, NSErrorFailingURLStringKey=https://api.XXX.com/XXX/XXX/}

наш сертификат отлично работает на других клиентах, таких как cURL и Android. При использовании HTTP наша реализация работает отлично.

кто-нибудь знает о каких-либо проблемах связанные с закрепленными сертификатами и AFNetworking? Если да, мы будем признательны за любые советы, которые у вас могут быть.

вот часть реализации:

+ (AFSecurityPolicy*)customSecurityPolicy {
   AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
   NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"filename" ofType:@"der"];
   NSData *certData = [NSData dataWithContentsOfFile:cerPath];
   [securityPolicy setAllowInvalidCertificates:NO];
   [securityPolicy setValidatesCertificateChain:NO];
   [securityPolicy setPinnedCertificates:@[certData]];
   return securityPolicy;
}

+ (AFHTTPRequestOperationManager*)customHttpRequestOperationManager {
   AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
   manager.securityPolicy = [self customSecurityPolicy]; // SSL
   return manager;
}

+(void)getRequestWithUrl:(NSString*)url success:(void(^)(AFHTTPRequestOperation *operation, id responseObject))success failure:(void(^) (AFHTTPRequestOperation *operation, NSError *error))failure {
   [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
   AFHTTPRequestOperationManager *manager = [HttpClient customHttpRequestOperationManager];
   manager.responseSerializer = [AFHTTPResponseSerializer serializer];
   [manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
       [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
       success(operation, responseObject);
   } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
       [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
       failure(operation, error);
   }];
}

спасибо!

8 ответов


после прочтения кода AFNetworking и проверки журналов изменений, вот что я должен был сделать, чтобы заставить это работать.

создайте объект AFSecurityPolicy с помощью AFSSLPinningModeCertificate:

AFSecurityPolicy* policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];

по умолчанию AFNetworking проверяет доменное имя сертификата. Наши сертификаты генерируются на серверной основе, и не все из них будут иметь доменное имя, поэтому нам нужно отключить это:

[policy setValidatesDomainName:NO];

так как сертификаты являются самоподписанными, они технически "недействительны", поэтому нам нужно разрешить и это:

[policy setAllowInvalidCertificates:YES];

наконец, AFNetworking попытается проверить сертификат на всем пути вверх по цепочке сертификатов, которая мне кажется, что она будет идти только вверх по цепочке к нашему CA, но по какой-то причине это не так, поэтому мы должны отключить это тоже:

[policy setValidatesCertificateChain:NO];

и это все! Установите политику безопасности в диспетчере запросов, как вы уже делаете, и она должна работать штраф.

Итак, резюмируем, все, что вам действительно нужно изменить в коде, который вы опубликовали, это:

A) Как Дэвид Caunt упомянуто, измените режим закрепления с AFSSLPinningModeNone до AFSSLPinningModeCertificate

и

B) добавьте строку, чтобы отключить проверку доменного имени:[policy setValidatesDomainName:NO]

еще одно примечание, AFNetworking теперь автоматически проверяет ваш пакет .файлы cer, поэтому, если вы должны были переименовать свой сертификат, чтобы иметь .расширение cer, вы можете устранить код для получения данных сертификата из пакета и установки закрепленных сертификатов.


поскольку вы инициализировали manager, вы можете сделать:

manager.securityPolicy.allowInvalidCertificates = YES;
manager.securityPolicy.validatesDomainName = NO;

и он будет работать для самозаверяющего сертификата


Я получал эту ошибку,Error Domain=NSURLErrorDomain Code=-1012 NSErrorFailingURLStringKey

только нижеприведенное изменение заставило его работать на меня.

self.validatesDomainName = NO;

вы создаете AFSecurityPolicy С SSLPinningMode режим AFSSLPinningModeNone.

для AFNetworking доверять серверу, с режимом закрепления установлен в AFSSLPinningModeNone, вы должны установить allowInvalidCertificates to YES, но это напротив чего вы пытаетесь достичь.

вместо этого вы должны создать свою политику безопасности с помощью режима закрепления AFSSLPinningModeCertificate или AFSSLPinningModePublicKey:

AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];

- (AFSecurityPolicy *)securityPolicy {
    NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"*.something.co.in" ofType:@"cer"];
    NSData *certData = [NSData dataWithContentsOfFile:cerPath];
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
    [securityPolicy setAllowInvalidCertificates:YES];
    [securityPolicy setPinnedCertificates:@[certData]];
    [securityPolicy setValidatesDomainName:NO];
    [securityPolicy setValidatesCertificateChain:NO];
    return securityPolicy;
}

это то, что ошибка генерации политики безопасности выглядит как -

- (AFSecurityPolicy *)securityPolicy {
    NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"*.something.co.in" ofType:@"cer"];
    NSData *certData = [NSData dataWithContentsOfFile:cerPath];
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
    [securityPolicy setAllowInvalidCertificates:NO];
    [securityPolicy setPinnedCertificates:@[certData]];
    [securityPolicy setValidatesDomainName:YES];
    return securityPolicy;
}

теперь придерживаясь правила "не исправить, если он не нарушен"


имея дело с аналогичной проблемой, это обычно для вещей, кажущихся нормальными через HTTPS-соединения браузера, так как многие браузеры кэшируют файлы сертификатов от третьих лиц, так что они не всегда должны быть загружены. Поэтому вполне может быть, что ваша цепочка сертификатов не полностью доверена, как вы, возможно, поверили.

другими словами, может показаться, что безопасно подключаться к браузеру, но в зависимости от настроек AFNetworking ваше приложение фактически не будет принимать цепочка сертификатов. После того, как вы убедитесь, что ваши настройки подходят, следующий шаг-убедиться, что цепочка сертификатов действительно так хороша, как вы думаете. Загрузите приложение под названием SSL Detective и запросите свой сервер. Вы также можете использовать www.ssldecoder.org. Убедитесь, что в вашей цепочке нет красных (ненадежных) элементов. Если есть, измените настройку сертификата на сервере.

учитывая, что настройки AFNetworking следующие:

 [securityPolicy setAllowInvalidCertificates:NO];
 [securityPolicy setValidatesCertificateChain:NO];

Это может не похоже на цепочку сертификатов, потому что она подписана самостоятельно. Возможно, Вам также придется переключить их на "да".


для меня, у меня use_frameworks! установить в my Podfile - проект не делает пользователя Swift, и я использовал Pods на AFNetworking. Комментируя это, исправил проблему для меня.


Я пробовал все это, но ничего не помогло, тогда я искал эту строку

' NSLog (@"для проверки доменного имени для самозаверяющих сертификатов необходимо использовать закрепление.");'

и ниже этой строки я изменил

' return NO;'
к

'вернуться да;'

и это магия.

спасибо.