zoukankan      html  css  js  c++  java
  • Https 单向验证 双向验证

    • 通讯原理
    participant Client
        participant Server
        Client->>Server: 以明文传输数据,主要有客户端支持的SSL版本等客户端支持的加密信息
        Server-->>Server: 服务端选择加密方式
        
        Server-->>Client: 服务端给客户端返回SSL版本、随机数等信息
        Client->>Client: 校验服务端证书是否合法、产生随机数
        
        Client->>Server: 使用服务端随机数加密数据发给服务端
        Server-->>Server: 服务端使用私钥解密客户端数据
        
        Server-->>Client: 使用收到的随机数,加密数据,返回给客户端
        Client->>Client: 客户端使用公钥解密数据
    
    • iOS客户端不验证证书
    //适配HTTPS
        AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
        [securityPolicy setValidatesDomainName:NO];
        securityPolicy.allowInvalidCertificates = YES;
        manager.securityPolicy = securityPolicy;
    

    设置代理后进行Charles代理拦截,以下为详细信息:(保证客户端不验证证书,保证在iOS设备上信任Charles证书)

    Client SSL handshake failed - Remote host closed connection during handshake
    客户端SSL握手失败-握手期间远程主机关闭连接
    
    You may need to configure your browser or application to trust the Charles Root Certificate. See SSL Proxying in the Help menu.
    您可能需要配置浏览器或应用程序以信任Charles根证书。请参见“帮助”菜单中的“SSL代理”。
    



    • AFN单项验证 客户端验证服务端证书
    Https在建立Socket连接之前,需要进行握手。
    
    1.客户端向服务端发送SSL协议版本号、加密算法种类、随机数等信息。
    2.服务端给客户端返回SSL协议版本号、加密算法种类、随机数等信息,同时也返回服务器端的证书,即公钥证书
    3.客户端使用服务端返回的信息验证服务器的合法性,包括:
    证书是否过期
    发型服务器证书的CA是否可靠
    返回的公钥是否能正确解开返回证书中的数字签名
    服务器证书上的域名是否和服务器的实际域名相匹配
    验证通过后,将继续进行通信,否则,终止通信
    4.客户端向服务端发送自己所能支持的对称加密方案,供服务器端进行选择
    5.服务器端在客户端提供的加密方案中选择加密程度最高的加密方式。
    6.服务器将选择好的加密方案通过明文方式返回给客户端
    7.客户端接收到服务端返回的加密方式后,使用该加密方式生成产生随机码,用作通信过程中对称加密的密钥,使用服务端返回的公钥进行加密,将加密后的随机码发送至服务器
    8.服务器收到客户端返回的加密信息后,使用自己的私钥进行解密,获取对称加密密钥。 
    9.在接下来的会话中,服务器和客户端将会使用该密码进行对称加密,保证通信过程中信息的安全。
    
    • AFN 双向验证方案 增加了服务端对客户端的验证
    - (void)POST:(NSString *)urlString
      Dictionary:(NSDictionary *)dic
        progress:(void (^)(NSProgress * _Nonnull))uploadProgress
         success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success
         failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
    {
        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
        //    设置超时时间
        [manager.requestSerializer willChangeValueForKey:@"timeoutInterval"];
        manager.requestSerializer.timeoutInterval = 30.f;
        [manager.requestSerializer didChangeValueForKey:@"timeoutInterval"];
        [manager.requestSerializer setValue:@"Content-Type" forHTTPHeaderField:@"application/json; charset=utf-8"];
        [manager setSecurityPolicy:[self customSecurityPolicy]];
        [self checkCredential:manager];
        
        NSData *data = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:nil];
        NSString *jsonString = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];    
        [manager POST:urlString parameters:jsonString progress:uploadProgress success:success failure:failure];
    }
    
    - (AFSecurityPolicy*)customSecurityPolicy {
        AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
        //tomcat1(1)
        NSString * cerPath = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"cer"];
        NSData *certData = [NSData dataWithContentsOfFile:cerPath];
        NSSet   *dataSet = [NSSet setWithArray:@[certData]];
        [securityPolicy setAllowInvalidCertificates:YES];
        [securityPolicy setPinnedCertificates:dataSet];
        [securityPolicy setValidatesDomainName:YES];
        
        return securityPolicy;
    }
    
    //校验证书
    - (void)checkCredential:(AFURLSessionManager *)manager
    {
        [manager setSessionDidBecomeInvalidBlock:^(NSURLSession * _Nonnull session, NSError * _Nonnull error) {
        }];
        __weak typeof(manager)weakManager = manager;
        [manager setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession*session, NSURLAuthenticationChallenge *challenge, NSURLCredential *__autoreleasing*_credential) {
            NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
            __autoreleasing NSURLCredential *credential =nil;
            NSLog(@"authenticationMethod=%@",challenge.protectionSpace.authenticationMethod);
            //判断是核验客户端证书还是服务器证书
            if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
                // 基于客户端的安全策略来决定是否信任该服务器,不信任的话,也就没必要响应挑战
                if([weakManager.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
                    // 创建挑战证书(注:挑战方式为UseCredential和PerformDefaultHandling都需要新建挑战证书)
                    NSLog(@"serverTrust=%@",challenge.protectionSpace.serverTrust);
                    credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
                    // 确定挑战的方式
                    if (credential) {
                        //证书挑战  设计policy,none,则跑到这里
                        disposition = NSURLSessionAuthChallengeUseCredential;
                    } else {
                        disposition = NSURLSessionAuthChallengePerformDefaultHandling;
                    }
                } else {
                    disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
                }
            } else {
                // client authentication
                SecIdentityRef identity = NULL;
                SecTrustRef trust = NULL;
                NSString *p12 = [[NSBundle mainBundle] pathForResource:@"app"ofType:@"p12"];
                NSFileManager *fileManager =[NSFileManager defaultManager];
                
                if(![fileManager fileExistsAtPath:p12])
                {
                    NSLog(@"client.p12:not exist");
                }
                else
                {
                    NSData *PKCS12Data = [NSData dataWithContentsOfFile:p12];
                    
                    if ([self extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12Data])
                    {
                        SecCertificateRef 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;
        }];
    }
    
    //读取p12文件中的密码
    - (BOOL)extractIdentity:(SecIdentityRef*)outIdentity andTrust:(SecTrustRef *)outTrust fromPKCS12Data:(NSData *)inPKCS12Data {
        OSStatus securityError = errSecSuccess;
        //client certificate password
        NSDictionary *optionsDictionary = [NSDictionary dictionaryWithObject:@"123456"
                                                                     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;
    }
    
    • 检查手机是否设置了代理 需要导入框架CFNetwork
      然后,这个方法是mrc的:需要添加-fno-objc-arc的flag
    - (BOOL) checkProxySetting {
        NSDictionary *proxySettings = (__bridge NSDictionary *)(CFNetworkCopySystemProxySettings());
        NSArray *proxies = (__bridge NSArray *)(CFNetworkCopyProxiesForURL((__bridge CFURLRef _Nonnull)([NSURL URLWithString:@"https://www.baidu.com"]), (__bridge CFDictionaryRef _Nonnull)(proxySettings)));
        NSLog(@"
    %@",proxies);
    
        NSDictionary *settings = proxies[0];
        NSLog(@"%@",[settings objectForKey:(NSString *)kCFProxyHostNameKey]);
        NSLog(@"%@",[settings objectForKey:(NSString *)kCFProxyPortNumberKey]);
        NSLog(@"%@",[settings objectForKey:(NSString *)kCFProxyTypeKey]);
    
        if ([[settings objectForKey:(NSString *)kCFProxyTypeKey] isEqualToString:@"kCFProxyTypeNone"])
        {
            NSLog(@"没设置代理");
            return NO;
        }
        else
        {
            
            NSLog(@"设置了代理");
            return YES;
        }
    
    }
    
  • 相关阅读:
    Oracle中有大量的sniped会话
    Error 1130: Host '127.0.0.1' is not allowed to connect to this MySQL server
    汉字转换为拼音以及缩写(javascript)
    高效率随机删除数据(不重复)
    vs2010 舒服背景 优雅字体 配置
    mvc中的ViewData用到webfrom中去
    jquery ajax return值 没有返回 的解决方法
    zShowBox (图片放大展示jquery版 兼容性好)
    动感效果的TAB选项卡 jquery 插件
    loading 加载提示······
  • 原文地址:https://www.cnblogs.com/lidarui/p/10413840.html
Copyright © 2011-2022 走看看