Detailed IOS development-using afnetworking to achieve HTTPS one-way authentication, two-way authentication _ios

Source: Internet
Author: User
Tags error code json

Since Apple announced January 1, 2017 the start of the mandatory use of HTTPS, Htpps has slowly become one of the objects discussed, not that the previous HTTPS did not appear, but this decision so that the developers did not expect, the blogger in 15 when the HTTPS interface, know that the depth of the pit, The reason is that they do not understand this knowledge and the information on the Internet, in addition to the blog is not right and wrong to each other, resulting in the online can hardly find the code, this point, the blogger said no exaggeration.

In view of this, the blogger has been trying to fill out this pit, add some correct code, for the vast number of developers to use, and has been put on hold, after a trial, bloggers will now tidy up the code released here, hoping to help the developers anxious to find.

1. First of all, how does the old afnetworking2.x come true?

Bloggers have seen several posts on the internet, which said some of the methods are correct, but not all right, because of the few blogs almost the same, bloggers can not determine the earliest that article is who wrote, so it is again under the instructions below the method:

1) pour into CLIENT.P12 certificate;

2 in the plist file to do as shown in Figure configuration:

3 Modify a class in afnetworking:

Find this file and add a method to it:

-(Osstatus) Extractidentity: (cfdataref) inp12data toidentity: (secidentityref*) identity { 
  Osstatus securityerror = errsecsuccess;
  Cfstringref Password = cfstr ("certificate Password"); 
  const void *keys[] = {Ksecimportexportpassphrase};
  const void *values[] = {password};
  Cfdictionaryref options = Cfdictionarycreate (null, keys, values, 1, NULL, NULL);
  Cfarrayref items = cfarraycreate (null, 0, 0, null); 
  Securityerror = Secpkcs12import (inp12data, Options, &items);
  if (Securityerror = = 0)   
  {
    Cfdictionaryref ident = Cfarraygetvalueatindex (items,0); 
    const void *tempidentity = NULL; 
    Tempidentity = Cfdictionarygetvalue (ident, ksecimportitemidentity);
    *identity = (secidentityref) tempidentity;  
  } 
  if (options) {  
    cfrelease (options);  
  }
  return securityerror;
}

Then modify one method:

Replace the code with the same name in nsurlconnectiondelegate with the following code.

-(void) connection: (Nsurlconnection *) connection Willsendrequestforauthenticationchallenge: ( Nsurlauthenticationchallenge *) Challenge {NSString *thepath = [[NSBundle mainbundle] pathforresource:@ "Client" OfType:
  @ "P12"];
  Pour into the certificate NSLog (@ "thepath===========%@", thepath);
  NSData *pkcs12data = [[NSData alloc] initwithcontentsoffile:thepath];

  Cfdataref Inpkcs12data = (__bridge cfdataref) pkcs12data;
  Secidentityref identity = NULL;

  Extract the ideneity from the certificate [self extractidentity:inpkcs12data toidentity:&identity];
  Seccertificateref certificate = NULL;

  Secidentitycopycertificate (identity, &certificate);
  const void *certs[] = {certificate};
  Cfarrayref Certarray = cfarraycreate (Kcfallocatordefault, certs, 1, NULL); Create a credential from the certificate and ideneity, then reply to the challenge with the credential (@ "//nslog
  tity=========%@ ", identity); Nsurlcredential *credential = [Nsurlcredential credentialwithiDentity:identity Certificates:nil Persistence:nsurlcredentialpersistencepermanent]; credential = [nsurlcredential credentialwithidentity:identity certificates: (__bridge NSArray*) CertArray Persistenc

  E:nsurlcredentialpersistencepermanent];

[Challenge.sender usecredential:credential Forauthenticationchallenge:challenge]; }

4) Initiating a request

 NSString *url = @ "xxxxxxxxxx";
  1. Obtain request Manager
  Afhttprequestoperationmanager *mgr = [Afhttprequestoperationmanager manager];
  2 set HTTPS request
  afsecuritypolicy *securitypolicy = [Afsecuritypolicy policywithpinningmode: Afsslpinningmodecertificate];
  Securitypolicy.allowinvalidcertificates = YES;
  Mgr.securitypolicy = securitypolicy;
  3. Send POST request

  [Mgr Post:url parameters:nil success:^ (afhttprequestoperation * _nonnull operation, id _nonnull Responseobject) {
    NSLog (@ "Responseobject:%@", responseobject);

  } failure:^ (Afhttprequestoperation * _ Nonnull operation, Nserror * _nonnull error) {
    NSLog (@ "error:%@", error);

  

To this, the old version of the afnetworking request HTTPS interface of two-way authentication done, but there is a problem, here need to change afnetworking code, not to mention the new afnetworking already have, in order to maintain the vitality of the code, the old should be abandoned, And after updating pods definitely replace the code is gone, is also a problem, do not worry, the following to say how to use the new afnetworking, and solve the pods update replacement code.

Finally, the use of old AF to request, only to use the Client.p12 file, and did not use the Server.cer, in the new inside is useful to, guess that the client chose to trust any certificate caused by the one-way verification.

Demo put in the last

2. To say how the new afnetworking3.x is going to come true.

1) pour into client.p12 and server.cer files

2 the setting within the plist, which is the same as the above:

3 Here you do not need to modify the code inside the class, but here you need to rewrite a method:

 NSString *url = @ "Https://test.niuniuhaoguanjia.com/3.0.0/?service=City.GetCityList";
  NSString *certfilepath = [[NSBundle mainbundle] pathforresource:@ "server" oftype:@ "CER"];
  NSData *certdata = [NSData Datawithcontentsoffile:certfilepath];
  Nsset *certset = [Nsset setwithobject:certdata]; Afsecuritypolicy *policy = [Afsecuritypolicy policywithpinningmode:afsslpinningmodecertificate
  Withpinnedcertificates:certset];
  Policy.allowinvalidcertificates = YES;

  Policy.validatesdomainname = NO;
  _manager = [Afhttpsessionmanager manager];
  _manager.securitypolicy = policy;
  _manager.requestserializer = [Afhttprequestserializer serializer];
  _manager.responseserializer = [Afhttpresponseserializer serializer]; _manager.responseserializer.acceptablecontenttypes = [Nsset setwithobjects:@ "Application/json", @ "Text/json", @ "
  Text/javascript ", @" Text/plain ", nil];
  Turn off caching to avoid interference test r _manager.requestserializer.cachepolicy = Nsurlrequestreloadignoringlocalcachedata; [_manager Setsessiondidbecomeinvalidblock:^ (Nsurlsession * _nonnull session, Nserror * _nonnull error) {NSLog (@ "Setsessiondidbecomeinva
  Lidblock ");
  }];
  Client request Validation Rewrite Setsessiondidreceiveauthenticationchallengeblock method __weak typeof (self) weakself = self; [_manager setsessiondidreceiveauthenticationchallengeblock:^nsurlsessionauthchallengedisposition (NSURLSession*
    Session, Nsurlauthenticationchallenge *challenge, nsurlcredential *__autoreleasing*_credential) {
    nsurlsessionauthchallengedisposition disposition = nsurlsessionauthchallengeperformdefaulthandling;
    __autoreleasing nsurlcredential *credential =nil; if ([Challenge.protectionSpace.authenticationMethod Isequaltostring:nsurlauthenticationmethodservertrust]) {if ([ WeakSelf.manager.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust Fordomain: Challenge.protectionSpace.host]) {credential = [nsurlcredential credentialForTrust:challenge.protectionSpace.serv
        Ertrust];
        if (credential) {  Disposition =nsurlsessionauthchallengeusecredential;
        else {disposition =nsurlsessionauthchallengeperformdefaulthandling;
      } else {disposition = Nsurlsessionauthchallengecancelauthenticationchallenge;
      } else {//client authentication Secidentityref identity = NULL;
      Sectrustref Trust = NULL;
      NSString *P12 = [[NSBundle mainbundle] pathforresource:@ "Client" oftype:@ "P12"];

      Nsfilemanager *filemanager =[nsfilemanager Defaultmanager]; if (![
      FileManager Fileexistsatpath:p12]) {NSLog (@ "client.p12:not exist");

        else {NSData *pkcs12data = [NSData DATAWITHCONTENTSOFFILE:P12]; if ([[[Weakself class]extractidentity:&identity andtrust:&trust Frompkcs12data:pkcs12data]) {SEC
          Certificateref certificate = NULL;
          Secidentitycopycertificate (identity, &certificate);
          Const void*certs[] = {certificate}; CFARrayref Certarray =cfarraycreate (Kcfallocatordefault, certs,1,null); Credential =[nsurlcredential credentialwithidentity:identity certificates: (__bridge NSArray*) CertArray Persistence:
          Nsurlcredentialpersistencepermanent];
        Disposition =nsurlsessionauthchallengeusecredential;
    }} *_credential = credential;
  return disposition;

 }];

4) Initiating a request

Step three and this step code is put together, please note oh
  [_manager get:url parameters:nil progress:^ (nsprogress * _nonnull downloadprogress) {

  } success:^ (Nsurlsessiondatatask * _nonnull task, id _nullable responseobject) {nsdictionary *dic
    = [NSJSONSerializa tion Jsonobjectwithdata:responseobject options:nsjsonreadingmutablecontainers error:nil];
    NSLog (@ "JSON:%@", DIC);
  } failure:^ (Nsurlsessiondatatask * _nullable task, Nserror * _nonnull error) {
    NSLog (@ "error:%@", error);

    NSData *data = [Error.userinfo objectforkey:@ "Com.alamofire.serialization.response.error.data"];
    NSString *str = [[NSString alloc]initwithdata:data encoding:nsutf8stringencoding];
    NSLog (@ "%@", str);
  

Add another method:

+ (BOOL) extractidentity: (secidentityref*) outidentity andtrust: (sectrustref *) outtrust frompkcs12data: (NSData *)
  Inpkcs12data {Osstatus securityerror = errsecsuccess;
                                 Client certificate Password nsdictionary*optionsdictionary = [nsdictionary dictionarywithobject:@ certificate Password]

  Forkey: (__bridge ID) ksecimportexportpassphrase];
  Cfarrayref items = cfarraycreate (null, 0, 0, NULL); Securityerror = Secpkcs12import (__bridge cfdataref) Inpkcs12data, (__bridge cfdictionaryref) optionsDictionary,&

  Items);
    if (Securityerror = = 0) {cfdictionaryref myidentityandtrust =cfarraygetvalueatindex (items,0);
    Const void*tempidentity =null;
    tempidentity= Cfdictionarygetvalue (myidentityandtrust,ksecimportitemidentity);
    *outidentity = (secidentityref) tempidentity;
    Const Void*temptrust =null;
    Temptrust = Cfdictionarygetvalue (myidentityandtrust,ksecimportitemtrust);
  *outtrust = (sectrustref) temptrust; else {NSLog (@ "Failedwith Error CODe%d ", (int) securityerror);
  return NO;
return YES;

 }

Yes, we're going to encapsulate it, but how do we package it? Bloggers tried to concentrate failed, is really baffled, I believe that the initiative to encapsulate the developers will also encounter the package after the request failed, perhaps you succeeded, but here need to pay attention to a block in the use of variables, specific can go to see how the Bo Master package.

Here, the new AF request HTTPS is over, want to see the package, demo put in the end.

3. One-way verification

Speaking of this, have to say a lot of online methods, are one-way verification as two-way, in fact, is not understand its principle, about the principle, please see here
The code implements AF all the same:

AF Plus this and the following method
  _manager.securitypolicy = [self customsecuritypolicy];



/**** SSL pinning ****/
-(afsecuritypolicy*) customsecuritypolicy {
  NSString *cerpath = [[NSBundle MainBundle] pathforresource:@ "Server" oftype:@ "CER"];
  NSData *certdata = [NSData Datawithcontentsoffile:cerpath];
  Afsecuritypolicy *securitypolicy = [Afsecuritypolicy policywithpinningmode:afsslpinningmodecertificate];
  [SecurityPolicy Setallowinvalidcertificates:yes];
  Nsset *set = [Nsset setwithobjects:certdata, nil];
  [SecurityPolicy Setpinnedcertificates:@[certdata]];
  /**** SSL pinning ****/return
  securitypolicy;
}

4.Demo Download Benefits

Because certificate security issues, Demo Certificate in the master deleted, please forgive me, please put your own certificate.

Old AF Access Httpsdemo

New AF Access Httpsdemo

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.