iOS AFNetworking framework HTTPS request configuration

iOS AFNetworking framework HTTPS request configuration

[Quoted from IamOkay's blog] Under Apple's mandatory requirement, data transmission on iOS must comply with the ATS (App Transefer Security) terms. About AFNetworking framework transmitting HTTPS data.

1. AllowsArbitraryLoads whitelist mechanism

NSAllowsArbitraryLoads is a product of the ATS promotion process. Of course, it may last for a long time or even forever. In order to access HTTP services, it is generally necessary to bypass ATS restrictions and configure the info.plist file.

  1. < key >NSAppTransportSecurity</ key >
  2. <dict>
  3. < key >NSAllowsArbitraryLoads</ key >
  4. < true />
  5. </dict>

This mechanism actually allows all HTTP and HTTPS access, which is obviously dangerous. Setting it to false can avoid bypassing ATS, but the question is, do we really need to turn this option off completely?

For example, for some file servers and CDN servers, configuring HTTPS will affect the transmission speed. In this case, HTTP is much more advantageous. Therefore, for HTTP transmission of such servers, we can also use the following method (setting a whitelist), and those outside the whitelist must use the HTTPS protocol.

  1. < key >NSAppTransportSecurity</ key >
  2. <dict>
  3. < key >NSExceptionDomains</ key >
  4. <dict>
  5. < key >lib.baidu.com</ key >
  6. <dict>
  7. < key >NSIncludesSubdomains</ key >
  8. < true />
  9. </dict>
  10. < key >oss.fastdfs.cn</ key >
  11. <dict>
  12. < key >NSIncludesSubdomains</ key >
  13. < true />
  14. </dict>
  15. </dict>
  16. </dict>

2. Certificate-free verification

Certificate verification is free. Generally speaking, the client certificate library will not verify the certificate transmitted by the server.

For example

  1. AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
  2. //Allow certificates issued by non-authoritative organizations
  3. manager.securityPolicy.allowInvalidCertificates = YES;
  4. //Does not verify domain name consistency
  5. manager.securityPolicy.validatesDomainName = NO ;
  6. // Turn off the cache to avoid interfering with the test
  7. manager.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
  8.  
  9. [manager GET:@ "https://www.baidu.com/s?wd=https" parameters:nil progress:nil
  10. success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
  11. NSLog(@ "%@" ,responseObject);
  12. } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
  13. NSLog(@ "%@" ,error);
  14. }];

This method makes our app vulnerable to man-in-the-middle attacks. The reason is not entirely because we set allowInvalidCertificates=YES and validatesDomainName=NO, but because the server's CA certificate is not added to the local certificate library. Any https can be forged as a server.

Therefore, we do not recommend using this method.

3. Certificate Verification

3.1 Classification of encryption standards

Certificate verification is divided into two categories: one-way authentication and two-way authentication.

In addition, we also need to distinguish the difference between certificates and certificate libraries. Certificate library types include PKCS12, JKS, BKS, etc. Among them, PKCS12 is an Internet standard that can be cross-platform and cross-language (supporting Android, iOS, WP, PC, JAVA, PHP...), JKS is a Java standard that can only be used on the Java platform and Java language, and BKS is the encryption standard of Bouncy Castle. As a supplement to the Android platform's support for SSL/TLS encryption suite PKCS12, its encryption strength is very high, but it is currently only used on the Android platform. The definition of a certificate is the digital signature information stored in the certificate library or a separate certificate file, such as crt, pem, cer, etc. Before talking about encryption, let's take a look at self-signed certificates.

3.2 Self-signed certificate vs. third-party authority certificate

Some people may wonder whether the effectiveness of self-signed certificates and certificates from third-party authorities is the same?

In fact, I think it is exactly the same. On the Internet, in services based on B/S architecture, the B side usually imports the root certificate (ROOT CA) of a third-party authority. In fact, it is to verify whether the CA certificate of the website is safe and whether it is issued by an authoritative security agency. The problem is that our App and Server are C/S architectures, and each app can only access a limited number of URLs at most. The app we make ourselves actually trusts the site URL we set, which means that we trust ourselves. Our certificate is only for secure data transmission and not being attacked by a man-in-the-middle, so there is no need to use (ROOT CA), but specifically, no one has tried this method so far to see if it can pass the audit.

I tried to communicate with a third-party CA certificate authority, and it seemed that they just said that this was Apple's regulation. In fact, there is nothing wrong with self-signed certificates in essence, as long as the key length, complexity, encryption method, etc. meet the requirements.

Therefore, if Apple really requires the use of a third-party CA ROOT signature rule, it is unreasonable. These problems cannot be avoided, but if Apple allows self-signed certificates, set allowInvalidCertificates=YES.

3.3 One-way Authentication

Files to prepare: server certificate library, server-exported certificate

One-way authentication actually means that only the client verifies the server's certificate, and the server does not need to verify the client's certificate.

Custom class: MyAFNetworking

  1. + (AFHTTPSessionManager *)manager;
  2. {
  3. static AFHTTPSessionManager *shareInstance = nil;
  4. static dispatch_once_t onceToken;
  5. dispatch_once(&onceToken, ^{
  6.  
  7. NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
  8. shareInstance = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:BaseHttpURLString] sessionConfiguration:configuration];
  9. //Set the request parameter type: JSON
  10. shareInstance.requestSerializer = [AFJSONRequestSerializer serializer];
  11. //Set the type of the server response: JSON (AFJSONResponseSerializer, AFHTTPResponseSerializer)
  12. shareInstance.responseSerializer = [AFJSONResponseSerializer serializer];
  13. //Set the request timeout
  14. shareInstance.requestSerializer.timeoutInterval = 20.0f;
  15. //Set ContentType
  16. shareInstance.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@ "application/json" , @ "text/html" , @ "text/json" , @ "text/plain" , @ "text/javascript" , @ "text/xml" , @ "image/jpeg" ,@ "image/png" , nil];
  17.  
  18. //https configuration
  19. NSString *cerPath = [[NSBundle mainBundle] pathForResource:@ "your certificate name" ofType:@ "cer" ];
  20. NSData *certData = [NSData dataWithContentsOfFile:cerPath];
  21. AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:[[NSSet alloc] initWithObjects:certData, nil]];
  22.  
  23. NSSet *dataSet = [[NSSet alloc] initWithObjects:certData, nil]; //You can add multiple server certificates here
  24.  
  25. // setPinnedCertificates sets the certificate file (maybe more than one certificate)
  26. [securityPolicy setPinnedCertificates:dataSet];
  27. // allowInvalidCertificates whether to allow invalid certificates
  28. [securityPolicy setAllowInvalidCertificates: NO ];
  29. // validatesDomainName whether to verify the domain name
  30. [securityPolicy setValidatesDomainName:YES];
  31.  
  32. shareInstance.securityPolicy = securityPolicy;
  33. });
  34. return shareInstance;
  35. }

Note: The certificate mentioned above is the cer or crt certificate obtained from the server. This type of certificate is a binary encoded certificate in the X509 Der format, not a Base64 encoded certificate in the X509 PAM format. For the generation of self-signed certificates, please refer to the following address

Common certificate formats and conversions

iOS asymmetric encryption and decryption

iOS self-signed certificate creation (self-signed)

3.4 Two-way authentication

Like iOS and Android, the client certificate store type can be a PKCS12 type pfx certificate, which contains a private key, public key, and certificate, and is protected by a password.

Two-way authentication is generally used for products with higher security requirements, such as financial apps, government apps and other special industries.

Files to prepare: server certificate library, server certificate trust library, server exported certificate, client certificate library, client certificate

Note [1]: The server certificate store can use the same certificate store as the server trust certificate store. The only thing to do is to import the client certificate.

Note [2]: Client certificates generally use a cross-platform PKCS12 certificate store (pfx or p12). The certificate store key must be remembered. This type of certificate store contains private keys, public keys, and certificates.

3.4.1 Trusting the Server

This step is used to verify the client certificate, which is exactly the same as one-way authentication.

Custom class: MyAFNetworking

  1. + (AFHTTPSessionManager *)manager;
  2. {
  3. static AFHTTPSessionManager *shareInstance = nil;
  4. static dispatch_once_t onceToken;
  5. dispatch_once(&onceToken, ^{
  6.  
  7. NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
  8. shareInstance = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:BaseHttpURLString] sessionConfiguration:configuration];
  9. //Set the request parameter type: JSON
  10. shareInstance.requestSerializer = [AFJSONRequestSerializer serializer];
  11. //Set the type of the server response: JSON (AFJSONResponseSerializer, AFHTTPResponseSerializer)
  12. shareInstance.responseSerializer = [AFJSONResponseSerializer serializer];
  13. //Set the request timeout
  14. shareInstance.requestSerializer.timeoutInterval = 20.0f;
  15. //Set ContentType
  16. shareInstance.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@ "application/json" , @ "text/html" , @ "text/json" , @ "text/plain" , @ "text/javascript" , @ "text/xml" , @ "image/jpeg" ,@ "image/png" , nil];
  17.  
  18. //https configuration
  19. NSString *cerPath = [[NSBundle mainBundle] pathForResource:@ "your certificate name" ofType:@ "cer" ];
  20. NSData *certData = [NSData dataWithContentsOfFile:cerPath];
  21. AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:[[NSSet alloc] initWithObjects:certData, nil]];
  22.  
  23. NSSet *dataSet = [[NSSet alloc] initWithObjects:certData, nil]; //You can add multiple server certificates here
  24.  
  25. // setPinnedCertificates sets the certificate file (maybe more than one certificate)
  26. [securityPolicy setPinnedCertificates:dataSet];
  27. // allowInvalidCertificates whether to allow invalid certificates
  28. [securityPolicy setAllowInvalidCertificates: NO ];
  29. // validatesDomainName whether to verify the domain name
  30. [securityPolicy setValidatesDomainName:YES];
  31.  
  32. shareInstance.securityPolicy = securityPolicy;
  33. });
  34. return shareInstance;
  35. }

3.4.2 Providing client certificates and certificate libraries

  1. /*
  2. *
  3. **
  4. * Create authentication conditions for the server to trust the client
  5. **
  6. */
  7. +(AFHTTPSessionManager *) createCredentialsClient
  8. {
  9. __block AFHTTPSessionManager * manager = [MyAFNetworking manager];
  10. [manager setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession*session, NSURLAuthenticationChallenge *challenge, NSURLCredential *__autoreleasing*_credential) {
  11. NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
  12. __autoreleasing NSURLCredential *credential =nil;
  13. if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
  14. if([manager.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
  15. credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
  16. if(credential) {
  17. disposition =NSURLSessionAuthChallengeUseCredential;
  18. } else {
  19. disposition =NSURLSessionAuthChallengePerformDefaultHandling;
  20. }
  21. } else {
  22. disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
  23. }
  24. } else {
  25. // client authentication
  26. SecIdentityRef identity = NULL ;
  27. SecTrustRef trust = NULL ;
  28. NSString *p12 = [[NSBundle mainBundle] pathForResource:@ "client" ofType:@ "pfx" ];
  29. NSFileManager *fileManager =[NSFileManager defaultManager];
  30.  
  31. if(![fileManager fileExistsAtPath:p12])
  32. {
  33. NSLog(@ "client.p12:not exist" );
  34. }
  35. else  
  36. {
  37. NSData *PKCS12Data = [NSData dataWithContentsOfFile:p12];
  38. #Load PKCS12 certificate, pfx or p12
  39. if ([MyAFNetworking extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12Data])
  40. {
  41. SecCertificateRef certificate = NULL ;
  42. SecIdentityCopyCertificate(identity, &certificate);
  43. const void*certs[] = {certificate};
  44. CFArrayRef certArray =CFArrayCreate(kCFAllocatorDefault, certs,1, NULL );
  45. credential =[NSURLCredential credentialWithIdentity:identity certificates:(__bridge NSArray*)certArray persistence:NSURLCredentialPersistencePermanent];
  46. disposition =NSURLSessionAuthChallengeUseCredential;
  47. }
  48. }
  49. }
  50. *_credential = credential;
  51. return disposition;
  52. }];
  53.  
  54. return manager;
  55. }
  56.  
  57. /**
  58. ** Load PKCS12 certificate, pfx or p12
  59. **
  60. **/
  61. +(BOOL)extractIdentity:(SecIdentityRef*)outIdentity andTrust:(SecTrustRef *)outTrust fromPKCS12Data:(NSData *)inPKCS12Data {
  62. OSStatus securityError = errSecSuccess;
  63. //client certificate password  
  64. NSDictionary*optionsDictionary = [NSDictionary dictionaryWithObject:@ "your p12 password"  
  65. forKey:(__bridge id)kSecImportExportPassphrase];
  66.  
  67. CFArrayRef items = CFArrayCreate( NULL , 0, 0, NULL );
  68. securityError = SecPKCS12Import((__bridge CFDataRef)inPKCS12Data,(__bridge CFDictionaryRef)optionsDictionary,&items);
  69.  
  70. if(securityError == 0) {
  71. CFDictionaryRef myIdentityAndTrust =CFArrayGetValueAtIndex(items,0);
  72. const void*tempIdentity = NULL ;
  73. tempIdentity= CFDictionaryGetValue (myIdentityAndTrust,kSecImportItemIdentity);
  74. *outIdentity = (SecIdentityRef)tempIdentity;
  75. const void*tempTrust = NULL ;
  76. tempTrust = CFDictionaryGetValue(myIdentityAndTrust,kSecImportItemTrust);
  77. *outTrust = (SecTrustRef)tempTrust;
  78. } else {
  79. NSLog(@ "Failedwith error code %d" ,( int )securityError);
  80. return   NO ;
  81. }
  82. return YES;
  83. }

Through the above methods, we can achieve two-way authentication

  1. AFHTTPSessionManager * manager = [MyAFNetworking createCredentialsClient];

<<:  Aiti Tribe Story Collection (14): Sharing helps improve operation and maintenance capabilities

>>:  Android teaches you how to interact with WebView and JS in five minutes

Recommend

An example analysis of Tieba user operation strategy!

User stratification refers to the purposeful form...

Case analysis: How are promotional marketing activities planned and implemented?

Next, let’s talk about the design forms of market...

BlackBerry CEO: It's unfair that Apple doesn't develop apps for us

[[126825]] BlackBerry CEO John Chen took a differ...

Strategies for creating popular articles on Xiaohongshu!

01 About the hot articles on Xiaohongshu 1) For a...

Why does Xiaomi want to engage in Internet finance during the bull market?

Today, Xiaomi Finance officially launched its Int...

Do you think being a vegetarian is healthy? Wrong! You can also get fatty liver!

Expert of this article: Huang Jia, Doctor of Medi...

Electric toothbrush VS ordinary toothbrush? The correct brushing method is the key!

“I brush my teeth three to five times a day, when...

From 0 to 1 million users, what operations need to do!

Let me introduce myself first. Before last year, ...