zoukankan      html  css  js  c++  java
  • iOS https认证

    1: AFNetworking 进行HTTPS认证

    //
    //  FFBaseNetwork.h
    //  Temp
    //
    //  Created by jisa on 2019/7/30.
    //  Copyright © 2019 jff. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface FFBaseNetwork : NSObject
    
    @end
    
    NS_ASSUME_NONNULL_END
    //
    //  FFBaseNetwork.m
    //  Temp
    //
    //  Created by jisa on 2019/7/30.
    //  Copyright © 2019 jff. All rights reserved.
    //
    
    #import "FFBaseNetwork.h"
    #import <AFNetworking/AFNetworking.h>
    
    @interface FFBaseNetwork ()
        
    @end
    
    
    @implementation FFBaseNetwork
    
    /// 进行HTTPS验证的核心代码
    - (void)FF_httpsValide:(AFHTTPSessionManager *)manager {
        /*
         *SSLPinning 证书绑定 客户端保存服务器端的证书,在建立https连接时比较服务器返回的证书是否和客户端的证书一致
         *
         *
         *AFSSLPinningModeNone 像浏览器一样在系统的信任机构列表里验证服务器端返回的证书
         *
         *AFSSLPinningModePublicKey 证书绑定,只验证公钥,不验证证书的有效期
         *
         *AFSSLPinningModeCertificate 证书绑定,第一步验证域名,有效期等信息。等而不验证证书信息
         */
        
        AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
        /// 是否允许无效的证书。 自制的https证书,在Apple中属于无效证书(不信任的证书)
        policy.allowInvalidCertificates = YES;
        /// 是否验证域名。默认为YES。如果使用的域名与证书域名不一致要设置为NO。
        policy.validatesDomainName = NO;
        NSString *path = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"cer"];
        NSData *data = [NSData dataWithContentsOfFile:path];
        ///
        policy.pinnedCertificates = [[NSSet alloc] initWithObjects:data, nil];
        manager.securityPolicy = policy;
        /// 质疑block
        __weak typeof(self) weakSelf = self;
        [manager setTaskDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession * _Nonnull session, NSURLSessionTask * _Nonnull task, NSURLAuthenticationChallenge * _Nonnull challenge, NSURLCredential *__autoreleasing  _Nullable * _Nullable credential) {
            __strong typeof(weakSelf) strongSelf = weakSelf;
            __autoreleasing NSURLCredential *_credential = NULL;
            NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
            if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
                /// 判断是否信任服务器证书
                /// 服务器证书是否可以被信任
                if ([policy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
                    _credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
                    if (_credential) {
                        disposition = NSURLSessionAuthChallengeUseCredential;
                    }
                }else {
                    disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
                }
            }else if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate]) {
                /// 客户端证书验证
                /// 双向认证才会走,服务器需要验证客户端的p12证书
                NSString *path = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"];
                NSData *p12Data = [NSData dataWithContentsOfFile:path options:0 error:NULL];
                SecIdentityRef identity = NULL;
                SecTrustRef trust = NULL;
                
                if ([strongSelf FF_extractIdentity:&identity andTrust:&trust fromData:p12Data]) {
                    SecCertificateRef certificateRef = NULL;
                    SecIdentityCopyCertificate(identity, &certificateRef);
                    const void *certs[] = {certificateRef};
                    CFArrayRef arrayRef = CFArrayCreate(NULL, certs, 1, NULL);
                    _credential = [[NSURLCredential alloc] initWithIdentity:identity certificates:(__bridge NSArray *)arrayRef persistence:NSURLCredentialPersistencePermanent];
                    disposition = NSURLSessionAuthChallengeUseCredential;
                }
            }
            *credential = _credential;
            return disposition;
            
        }];
    }
    /// 从客户端证书中获取 SecIdentity 和 SecTrustRef。
    - (BOOL)FF_extractIdentity:(SecIdentityRef *)outIdentity andTrust:(SecTrustRef *)outTrust fromData:(NSData *)data {
        NSDictionary *dic = @{(__bridge NSString *)kSecImportExportPassphrase : @"123456"};
        
        CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
        OSStatus status = SecPKCS12Import((__bridge CFDataRef)data, (__bridge CFDictionaryRef)dic, &items);
        if (status == errSecSuccess) {
            CFDictionaryRef identityAndTrust = CFArrayGetValueAtIndex(items, 0);
            const void *tempIdentity = NULL;
            tempIdentity = CFDictionaryGetValue(identityAndTrust, kSecImportItemIdentity);
            *outIdentity = (SecIdentityRef)tempIdentity;
            const void *tempTrust = CFDictionaryGetValue(identityAndTrust, kSecImportItemTrust);
            *outTrust = (SecTrustRef)tempTrust;
            return YES;
        }else {
            return NO;
        }
    }
        
    - (AFHTTPSessionManager *)manager {
        AFHTTPSessionManager *manager = [[AFHTTPSessionManager manager] initWithBaseURL:NULL];
        manager.requestSerializer = [AFJSONRequestSerializer serializer];
        manager.responseSerializer = [AFJSONResponseSerializer serializer];
        manager.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
        manager.requestSerializer.timeoutInterval = 30;
        manager.responseSerializer.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"json/text", nil];
        return manager;
    }
        
    @end

    2: SDWebImage 中使用HTTPS如果是双向认证的话,设置客户端证书如下

      如果是自制的HTTPS证书 在 SDWebImageDownloaderOptions 中要包括 SDWebImageDownloaderAllowInvalidSSLCertificates。允许无效的证书

    //
    //  SDWebImageDownloader+AFNHTTPS.m
    //  TongCheng
    //
    //  Created by jisa on 2019/7/30.
    //  Copyright © 2019 jisa. All rights reserved.
    //
    
    #import "SDWebImageDownloader+AFNHTTPS.h"
    
    @implementation SDWebImageDownloader (AFNHTTPS)
    + (void)load {
        [SDWebImageDownloader sharedDownloader].urlCredential = [self myURLCredential];
    }
    
    + (NSURLCredential *)myURLCredential {
        SecIdentityRef identity = NULL;
        NSString *p12Path = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"];
        NSData *data = [NSData dataWithContentsOfFile:p12Path];
        [self extractIdentity:&identity fromPKCS12Data:data];
        SecCertificateRef certificate = NULL;
        SecIdentityCopyCertificate(identity, &certificate);
        const void *certs[] = {certificate};
        CFArrayRef cerArray = CFArrayCreate(kCFAllocatorMalloc, certs, 1, NULL);
        return [NSURLCredential credentialWithIdentity:identity certificates:(__bridge NSArray *)cerArray persistence:NSURLCredentialPersistencePermanent];
        
    }
    
    
    + (BOOL)extractIdentity:(SecIdentityRef*)outIdentity fromPKCS12Data:(NSData *)inPKCS12Data {
        OSStatus securityError = errSecSuccess;
        //client certificate password
        NSDictionary*optionsDictionary = [NSDictionary dictionaryWithObject:@"tc888888"
                                                                     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;
            return YES;
        } else {
            NSLog(@"Failedwith error code %d",(int)securityError);
            return NO;
        }
    }
    @end
  • 相关阅读:
    LeetCode-top100-3. 无重复字符的最长子串
    最长单调递增子序列 POJ 3903 Stock Exchange .
    并查集 POJ 1988 Cube Stacking
    贪心初步 hdu1789 Doing Homework again
    并查集初步题目(2)
    并查集初步题目(1)
    【python】引用模块,以及初探__init__.py
    Python 模块里函数的调用方法和import语句的作用(初学者版)
    二分查找算法
    python之内置函数,匿名函数
  • 原文地址:https://www.cnblogs.com/jisa/p/11271600.html
Copyright © 2011-2022 走看看