English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Principio de encapsulación de solicitud de datos y autenticación de certificado de firma propia de HTTPS en iOS

Resumen: En WWDC 2016la conferencia de desarrolladores, Apple anunció un último plazo: hasta2017año1mes1dia, todas las aplicaciones en el App Store deben activar la función de seguridad de transporte de aplicaciones. App Transport Security (ATS) es una función de protección de privacidad introducida por Apple en iOS 9es una función de protección de privacidad introducida, que bloquea la carga de recursos HTTP en texto plano, la conexión debe pasar por HTTPS más seguro. Actualmente, Apple permite a los desarrolladores desactivar temporalmente ATS, pueden continuar utilizando conexiones HTTP, pero todos los aplicaciones en el App Store deben usar ATS obligatoriamente para fines oficiales a finales de año.

el marco utilizado en el proyecto es AFNetworking 3.0 y versiones superiores, debido a ATS, iOS solo permite usar enlaces que comiencen con HTTPS, en2016año12mes3antes del 0 día, Apple permitía eludir ATS, como se muestra en la siguiente imagen:

pero desde2017año1mes1A partir de este mes, Apple ya no aceptará aplicaciones que utilicen http para cargar recursos, por lo tanto, este artículo se centrará en cómo utilizar AFN para autenticar certificados de firma HTTPS (Nota: para certificados autenticados por instituciones de CA, no es necesario realizar la autenticación, simplemente utilice enlaces que comiencen con HTTPS para acceder a datos y cargar páginas). El proyecto se ha subido a GitHub (si necesita referirse al código fuente, haga clic en el enlace):HttpsSignatureCertificate_jb51.rar

1,establecer una clase base Aquí se llama AKNetPackegeAFN

 1> .h archivo, crear los métodos Get y Post necesarios

#import <Foundation/Foundation.h>
typedef enum{
  AKNetWorkGET ,  /**< GET solicitud */
  AKNetWorkPOST = 1 /**< POST solicitud */
}AKNetWorkType;
typedef void (^HttpSuccess)(id json);
typedef void (^HttpErro)(NSError* error);
@interface AKNetPackegeAFN : NSObject
+(instancetype)shareHttpManager;
/*
 *
 netWorkType:modo de solicitud GET o POST
 signature:si se utiliza el certificado de firma, escriba directamente el nombre del certificado, de lo contrario, escriba nil
 api:interfaz de URL de solicitud
 parameters:parámetros de solicitud
 sucess:valor de retorno al tener éxito en la solicitud
 fail:valor de retorno al fallar la solicitud
 *
 */
- (void)tipoDeRed:(AKNetWorkType)tipoDeRed Firma:(NSString *)API de firma:(NSString *)parámetros de API:(NSDictionary *)parámetros Éxito:(HttpSuccess)sucess Fallo:(HttpErro)fail;
@end

2> .m archivo, importe el archivo de encabezado AFNetworking.h, cree la propiedad Manager y realice la implementación del método compartirHttpManager

#import "AKNetPackegeAFN.h"
#import "AFNetworking.h"
@interface AKNetPackegeAFN()
@property (nonatomic,strong) AFHTTPSessionManager *manager;
@end
@implementation AKNetPackegeAFN
+(instancetype)compartirHttpManager{
  static dispatch_once_t once = 0;
  static AKNetPackegeAFN *httpManager = nil;
  dispatch_once(&once, ^(void){
    httpManager = [[self alloc]init];
  });
  return httpManager;
}

2implementación de métodos Get y Post

Al usarlo, convierta el certificado proporcionado por el servidor en formato .cer y arrástrelo al directorio raíz del proyecto, luego vincúlelo en el método. Por ejemplo, el nombre del certificado proporcionado por el servidor es: Kuture.crt. Después de recibir el certificado, haga doble clic para instalarlo, luego abra el llavero, haga clic derecho en el certificado llamado Kuture y exporte, seleccione el sufijo .cer y luego presione Aceptar. Como se muestra en la siguiente imagen:

  -->     -->

-->

encapsulación de métodos GET y POST

- (void)tipoDeRed:(AKNetWorkType)tipoDeRed Firma:(NSString *)API de firma:(NSString *)parámetros de API:(NSDictionary *)parámetros Éxito:(HttpSuccess)sucess Fallo:(HttpErro)fail{
  //activar el modo de verificación de certificados
  AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
  //¿Permitir el uso de certificados autofirmados?
  signature == nil ? (void)(securityPolicy.allowInvalidCertificates = NO):(securityPolicy.allowInvalidCertificates = YES);
  //¿Es necesario verificar el nombre de dominio?
  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) {
      //Obtener el objeto de confianza del servidor
      SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
      //Importar certificado de firma autógena
      NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"tu nombre de certificado" ofType:@"cer"];
      NSData *cerData = [NSData dataWithContentsOfFile:cerPath];
      if (!cerData) {
        NSLog(@"==== El archivo .cer es 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");
      //Establecer el certificado leído como el certificado raíz de serverTrust
      OSStatus status = SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)caArray);
      SecTrustSetAnchorCertificatesOnly(serverTrust, NO);
      NSCAssert(errSecSuccess == status, @"SectrustSetAnchorCertificates failed");
      //Elegir la forma de manejar la autenticación de desafío
      NSURLSessionAuthChallengeDisposition disposición = NSURLSessionAuthChallengePerformDefaultHandling;
      __autoreleasing NSURLCredential *credential = nil;
      //Método de autenticación de desafío de URLAuthenTicationMethodServerTrust
      if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        //decidir si confiar en el servidor basado en la política de seguridad del cliente, no responder al desafío si no se confía
        if ([weakSelf.manager.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
          //crear certificado de desafío
          credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
          //confirmar modo de desafío
          if (credential) {
            disposition = NSURLSessionAuthChallengeUseCredential;
          } else {
            disposition = NSURLSessionAuthChallengePerformDefaultHandling;
          }
        } else {
          //cancelar desafío
          disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
        }
      } else {
        disposition = NSURLSessionAuthChallengePerformDefaultHandling;
      }
      return disposition;
    };
  }
  if (netWorkType == 0){
    [_manager GET:api parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
    } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
      if (sucess){
        sucess(responseObject);
      else{
        NSLog(@"Excepción de conexión o red no existe");
      }
    }; failure:^(NSURLSessionDataTask * _Nullable tarea, NSError * _Nonnull error) {
      fail(error);
    };
  } else if (netWorkType == 1){
    [_manager POST:api parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
    } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
      if (sucess){
        sucess(responseObject);
      else{
        NSLog(@"Excepción de conexión o red no existe");
      }
    }; failure:^(NSURLSessionDataTask * _Nullable tarea, NSError * _Nonnull error) {
      fail(error);
    };
  }  
}

2  Método de uso, en la clase que necesita obtener o transmitir datos, importe directamente el archivo de encabezado AKNetPackegeAFN.h y realice el método, como se muestra a continuación:

//Crear objeto
  //Si es un certificado de firma autógena, primero realice el enlace del certificado en el método correspondiente de AKNetPackegeAFN antes de usarlo (el certificado se puede arrastrar directamente al proyecto)
  /*
   *
   netWorkType:modo de solicitud GET o POST
   signature:si se utiliza el certificado de firma, escriba directamente el nombre del certificado, de lo contrario, escriba nil
   api:interfaz de URL de solicitud
   parameters:parámetros de solicitud
   sucess:valor de retorno al tener éxito en la solicitud
   fail:valor de retorno al fallar la solicitud
   *
   */
  AKNetPackegeAFN *netHttps = [AKNetPackegeAFN shareHttpManager];
  [netHttps netWorkType:tipo de solicitud Signature:nombre del certificado API:URL de solicitud Parameters:parámetros Success:^(id json) {
    NSLog(@"Json:%@",json);
  }; Fail:^(NSError *error) {
    NSLog(@"Error:%@",error);
  };

Esto es todo el contenido de este artículo, espero que pueda ayudar a su aprendizaje y también espero que todos los amigos apoyen el tutorial de grito.

Declaración: Este artículo se ha obtenido de la red, el copyright pertenece al propietario original, el contenido se ha contribuido y cargado de manera autónoma por los usuarios de Internet, este sitio web no posee los derechos de propiedad, no se ha realizado la edición humana y no asume la responsabilidad legal correspondiente. Si encuentra contenido sospechoso de infracción de derechos de autor, por favor envíe un correo electrónico a: notice#w3Declaración: El contenido de este artículo se obtiene de la red, el copyright pertenece al propietario original, el contenido se contribuye y carga de manera autónoma por los usuarios de Internet, este sitio web no posee los derechos de propiedad, no se ha realizado la edición humana y no asume la responsabilidad legal correspondiente. Si encuentra contenido sospechoso de infracción de derechos de autor, por favor envíe un correo electrónico a: notice#w

Te gustará