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

Princípio de autenticação de certificado SSL autoassinado e encapsulamento da solicitação de dados no iOS

Resumo: No WWDC 2016na conferência de desenvolvedores, a Apple anunciou um prazo final: até2017ano1mês1dia, todos os aplicativos no App Store devem habilitar a função de segurança de transporte de aplicativos. O App Transport Security (ATS) é um recurso de proteção de privacidade introduzido pela Apple no iOS 9um recurso de proteção de privacidade introduzido, que bloqueia a carga de recursos HTTP em texto puro, a conexão deve passar por HTTPS mais seguro. A Apple permite que os desenvolvedores desative temporariamente o ATS, continuando a usar conexões HTTP, mas até o final do ano, todos os aplicativos nas lojas oficiais devem usar obrigatoriamente o ATS.

o framework usado no projeto é AFNetworking 3.0 e versões posteriores, devido ao ATS, o iOS permite usar apenas links começando com Https, no2016ano12mês30 antes do dia, a Apple permitiu contornar o ATS, conforme mostrado na figura a seguir:

mas desde2017ano1mês1A partir de hoje, não serão mais aceitos aplicativos que utilizem http para carregar recursos, portanto, este artigo explica como usar o AFN para autenticar certificados de assinatura (Nota: para certificados autenticados por CA, não é necessário autenticar, você pode usar links começando com Https para acessar dados e carregar páginas). O projeto foi carregado no GitHub (para referenciar o código, clique no link):HttpsSignatureCertificate_jb51.rar

1,criar uma classe raiz Aqui chamada AKNetPackegeAFN

 1> Arquivo .h, criar os métodos Get e Post necessários

#import <Foundation/Foundation.h>
typedef enum{
  AKNetWorkGET ,  /**< GET solicitação */
  AKNetWorkPOST = 1 /**< POST solicitação */
}AKNetWorkType;
typedef void (^HttpSuccess)(id json);
typedef void (^HttpErro)(NSError* error);
@interface AKNetPackegeAFN : NSObject
+(instancetype)shareHttpManager;
/*
 *
 netWorkType:Modo de solicitação GET ou POST
 signature:Uso de certificado de assinatura, se for, escreva o nome do certificado diretamente, se não, preencha nil
 api:Interface de URL de solicitação
 parameters:Parâmetros da solicitação
 sucess:Retorno ao sucesso na solicitação
 fail:Retorno ao falhar na solicitação
 *
 */
- (void)tipoDeRede:(AKNetWorkType)tipoDeRede Assinatura:(NSString *)assinatura API:(NSString *)parâmetros API:(NSDictionary *)parâmetros Sucesso:(HttpSuccess)sucess Falha:(HttpErro)fail;
@end

2> Arquivo .m, importe o cabeçalho AFNetworking.h, crie a propriedade Manager e implemente o método shareHttpManager

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

2Implementação dos métodos Get e Post

Ao usar, converta o certificado fornecido pelo servidor para o formato .cer, arraste-o para a raiz do projeto e vincule-o no método. Por exemplo, o nome do certificado fornecido pelo servidor é: Kuture.crt. Após receber o certificado, clique duas vezes para instalá-lo, abra a chave, clique com o botão direito no certificado chamado Kuture, exporte e selecione o sufixo .cer, então clique em Confirmar. Como mostrado na figura a seguir:

  -->     -->

-->

encapsulamento de métodos GET e POST

- (void)tipoDeRede:(AKNetWorkType)tipoDeRede Assinatura:(NSString *)assinatura API:(NSString *)parâmetros API:(NSDictionary *)parâmetros Sucesso:(HttpSuccess)sucess Falha:(HttpErro)fail{
  //ativar o modo de verificação de certificado
  AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
  //Se permite usar certificados autoassinados
  signature == nil ? (void)(securityPolicy.allowInvalidCertificates = NO):(securityPolicy.allowInvalidCertificates = YES);
  //Se precisa validar o nome do domínio
  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) {
      //Obter o objeto de confiança do servidor
      SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
      //Importar certificado autoassinado
      NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"Seu nome de certificado" ofType:@"cer"];
      NSData *cerData = [NSData dataWithContentsOfFile:cerPath];
      if (!cerData) {
        NSLog(@"==== O arquivo .cer é nulo ====");
        return 0;
      }
      NSArray *cerArray = @[cerData];
      weakSelf.manager.securityPolicy.pinnedCertificates = cerArray;
      SecCertificateRef caRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)cerData);
      NSCAssert(caRef != nil, @"caRef é nulo");
      NSArray *caArray = @[(__bridge id)(caRef)];
      NSCAssert(caArray != nil, @"caArray é nulo");
      //Definir o certificado lido como o certificado raiz de serverTrust
      OSStatus status = SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)caArray);
      SecTrustSetAnchorCertificatesOnly(serverTrust, NO);
      NSCAssert(errSecSuccess == status, @"Falha ao configurar certificados de referência Sectrust");
      //Escolher o modo de tratamento de autenticação de desafio
      NSURLSessionAuthChallengeDisposition disposição = NSURLSessionAuthChallengePerformDefaultHandling;
      __autoreleasing NSURLCredential *credential = nil;
      //Método de autenticação de desafio de URLAuthenTicationMethodServerTrust
      if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        //decidir se confiar no servidor com base na política de segurança do cliente, se não confiar, não responder ao desafio
        if ([weakSelf.manager.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
          //criar certificado de desafio
          credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
          //confirmar método de desafio
          if (credential) {
            disposition = NSURLSessionAuthChallengeUseCredential;
          } else {
            disposition = NSURLSessionAuthChallengePerformDefaultHandling;
          }
        } else {
          //cancelar desafio
          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(@"Exceção de conexão ou rede não existe");
      }
    }; failure:^(NSURLSessionDataTask * _Nullable tarefa, 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(@"Exceção de conexão ou rede não existe");
      }
    }; failure:^(NSURLSessionDataTask * _Nullable tarefa, NSError * _Nonnull error) {
      fail(error);
    };
  }  
}

2  Método de uso, em classes que precisam de obtenção ou transmissão de dados, importe diretamente o cabeçalho AKNetPackegeAFN.h e realize o método, conforme mostrado a seguir:

//Criação de objeto
  //Se for um certificado de assinatura auto, faça o bind do certificado no método correspondente do AKNetPackegeAFN antes de usar (o certificado pode ser arrastado diretamente para o projeto)
  /*
   *
   netWorkType:Modo de solicitação GET ou POST
   signature:Uso de certificado de assinatura, se for, escreva o nome do certificado diretamente, se não, preencha nil
   api:Interface de URL de solicitação
   parameters:Parâmetros da solicitação
   sucess:Retorno ao sucesso na solicitação
   fail:Retorno ao falhar na solicitação
   *
   */
  AKNetPackegeAFN *netHttps = [AKNetPackegeAFN shareHttpManager];
  [netHttps netWorkType:Tipo de Requisição Signature:Nome do Certificado API:URL de Requisição Parameters:Parâmetros Sucesso:^(id json) {
    NSLog(@"Json:%@",json);
  }; Fail:^(NSError *error) {
    NSLog(@"Error:%@",error);
  };

Isso é tudo o que há no artigo, espero que ajude no seu aprendizado e que você apóie o tutorial Grito.

Declaração: O conteúdo deste artigo é extraído da internet, pertence ao respectivo proprietário, o conteúdo é contribuído e carregado voluntariamente pelos usuários da internet, este site não possui direitos de propriedade, não foi editado manualmente e não assume responsabilidades legais relacionadas. Se você encontrar conteúdo suspeito de violação de direitos autorais, bem-vindo a enviar e-mail para: notice#w3Aviso: O conteúdo deste artigo foi extraído da internet, pertence ao respectivo proprietário, o conteúdo foi contribuído e carregado voluntariamente pelos usuários da internet, este site não possui direitos de propriedade, não foi editado manualmente e não assume responsabilidades legais relacionadas. Se você encontrar conteúdo suspeito de violação de direitos autorais, bem-vindo a enviar e-mail para: notice#w

Você também pode gostar