English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Обзор: На конференции разработчиков WWDC 2016 компания Apple объявила о крайнем сроке: до 1 января 2017 года все приложения в App Store должны будут включить функцию безопасности App Transport Security. App Transport Security (ATS) - это функция защиты конфиденциальности, введенная Apple в iOS 9, которая блокирует загрузку ресурсов HTTP в открытом тексте и требует использования более безопасного HTTPS для подключения. В настоящее время Apple позволяет разработчикам временно отключать ATS и продолжать использовать подключения HTTP, но до конца года все приложения в официальных магазинах будут вынуждены использовать ATS.
В проекте используются фреймворки AFNetworking 3.0 и выше, из-за ATS iOS позволяет использовать только ссылки, начинающиеся с Https, до 30 декабря 2016 года Apple позволял обойти ATS, как показано на рисунке:
Но с 1 января 2017 года больше не будут принимать приложения, использующие http для загрузки ресурсов, поэтому в этой статье рассказывается, как использовать AFN для сертификации самознаковых сертификатов (Примечание: для сертификатов, сертифицированных CA, сертификация не требуется,可以直接 использовать ссылки, начинающиеся с Https, для доступа к данным и загрузки страниц). Проект загружен на GitHub (если нужно参阅 исходный код, нажмите на ссылку):HttpsSignatureCertificate_jb51.rar
1. Создайте базовый класс, назовем его AKNetPackegeAFN
1> .h файл, создайте необходимые методы Get и Post
#import <Foundation/Foundation.h> typedef enum{ AKNetWorkGET , /**< GET запрос */ AKNetWorkPOST = 1 /**< POST запрос */ }AKNetWorkType; typedef void (^HttpSuccess)(id json); typedef void (^HttpErro)(NSError* error); @interface AKNetPackegeAFN : NSObject +(instancetype)shareHttpManager; /* * netWorkType:способ запроса GET или POST signature:использовать ли сертификат подписи, если да, то введите имя сертификата, если нет, то введите nil api:URL интерфейса запроса parameters:параметры запроса sucess:возврат при успешном запросе fail:возврат при ошибке запроса * */ - (void)netWorkType:(AKNetWorkType)netWorkType Signature:(NSString *)signature API:(NSString *)api Parameters:(NSDictionary *)parameters Success:(HttpSuccess)sucess Fail:(HttpErro)fail; @end
2> .m файл, импортируйте заголовочный файл AFNetworking.h, создайте атрибут Manager и реализуйте метод класса shareHttpManager
#import "AKNetPackegeAFN.h" #import "AFNetworking.h" @interface AKNetPackegeAFN() @property (nonatomic,strong) AFHTTPSessionManager *manager; @end @implementation AKNetPackegeAFN +(instancetype)shareHttpManager{ static dispatch_once_t onece = 0; static AKNetPackegeAFN *httpManager = nil; dispatch_once(&onece, ^(void){ httpManager = [[self alloc]init]; }); return httpManager; }
2. Реализация методов Get и Post
При использовании сертификат, предоставленный сервером, нужно преобразовать в формат .cer и перетащить в корневую директорию проекта, затем привязать в методе. Например, имя сертификата, предоставленного сервером: Kuture.crt. После получения сертификата дважды щелкните по нему, чтобы установить, затем откройте ключевойchain, щелкните правой кнопкой по сертификату с именем Kuture, выберите экспорт в формате .cer и нажмите «ОК». Как показано на рисунке:
--> -->
-->
Обертка методов GET и POST
- (void)netWorkType:(AKNetWorkType)netWorkType Signature:(NSString *)signature API:(NSString *)api Parameters:(NSDictionary *)parameters Success:(HttpSuccess)sucess Fail:(HttpErro)fail{ // Включение режима проверки сертификатов AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate]; // Разрешение использования самоподписанных сертификатов signature == nil ? (void)(securityPolicy.allowInvalidCertificates = NO) : (securityPolicy.allowInvalidCertificates = YES); //необходимо ли проверять имя домена securityPolicy.validatesDomainName = NO; _manager = [[AFHTTPSessionManager alloc]initWithBaseURL:[NSURL URLWithString:api]]; _manager.responseSerializer = [AFJSONResponseSerializer serializer]; _manager.securityPolicy = securityPolicy; _manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"application/xml",@"text/xml",@"text/json",@"text/plain",@"text/javascript",@"text/html", nil]; if (signature != nil){ __weak typeof(self) weakSelf = self; [_manager setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential *__autoreleasing *_credential) { //получение доверительного объекта сервера SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust]; //импорт самоподписанного сертификата NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"твоё имя сертификата" ofType:@"cer"]; NSData *cerData = [NSData dataWithContentsOfFile:cerPath]; if (!cerData) { NSLog(@"==== .cer файл nil ===="); return 0; } NSArray *cerArray = @[cerData]; weakSelf.manager.securityPolicy.pinnedCertificates = cerArray; SecCertificateRef caRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)cerData); NSCAssert(caRef != nil, @"caRef is nil"); NSArray *caArray = @[(__bridge id)(caRef)]; NSCAssert(caArray != nil, @"caArray is nil"); //将读取到的证书设置为serverTrust的根证书 OSStatus status = SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)caArray); SecTrustSetAnchorCertificatesOnly(serverTrust, NO); NSCAssert(errSecSuccess == status, @"SectrustSetAnchorCertificates failed"); //选择质询认证的处理方式 NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling; __autoreleasing NSURLCredential *credential = nil; //NSURLAuthenTicationMethodServerTrust质询认证方式 if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { //基于客户端的安全策略来决定是否信任该服务器,不信任则不响应质询 if ([weakSelf.manager.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) { //Создание сертификата запроса credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; //Подтверждение метода запроса if (credential) { disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge; return disposition; if (netWorkType == 0){ } return disposition; //Отмена вызова disposition = NSURLSessionAuthChallengePerformDefaultHandling; } return disposition; if (netWorkType == 0){ } [_manager GET:api parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) { }; } else if (netWorkType == 1){ } } if (sucess){ sucess(responseObject); } NSLog(@"Сбой подключения или отсутствует сеть"); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { fail(error); }; [_manager POST:api parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) { success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { } if (sucess){ sucess(responseObject); } NSLog(@"Сбой подключения или отсутствует сеть"); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { fail(error); }; } }
2 Использование, в классе, где необходимо получить или передать данные, напрямую импортируйте заголовочный файл AKNetPackegeAFN.h и реализуйте метод, как показано ниже:
//Создание объекта //Если это самоподписанный сертификат, перед использованием сертификат необходимо привязать к методу AKNetPackegeAFN (сертификат можно просто перетащить в проект) /* * netWorkType:способ запроса GET или POST signature:использовать ли сертификат подписи, если да, то введите имя сертификата, если нет, то введите nil api:URL интерфейса запроса parameters:параметры запроса sucess:возврат при успешном запросе fail:возврат при ошибке запроса * */ AKNetPackegeAFN *netHttps = [AKNetPackegeAFN shareHttpManager]; [netHttps netWorkType:тип_запроса Signature:имя_сертификата API:URL_запроса Parameters:параметры Success:^(id json) { NSLog(@"Json:%@",json); }; Fail:^(NSError *error) { NSLog(@"Ошибка:%@",error); };
Вот и все, что есть в этой статье, надеюсь, это поможет вам в изучении. Также希望大家多多支持呐喊教程。
Заявление: содержимое этой статьи взято из Интернета, авторские права принадлежат соответствующему автору. Контент предоставлен пользователями Интернета, загружен пользователями самостоятельно, сайт не имеет права собственности, не был отредактирован вручную и не несет ответственности за связанные с этим юридические вопросы. Если вы обнаружите подозрительное содержимое, пожалуйста, отправьте письмо по адресу: notice#oldtoolbag.com (при отправке письма замените # на @) для сообщения о нарушении авторских прав,并提供 соответствующие доказательства. Если подтвердится, сайт немедленно удалят подозрительное содержимое.