iOS https

作者: PandaXiong | 来源:发表于2017-03-20 15:59 被阅读195次

    公司使用https,但是与后台调试接口的时候却死活调试失败。我在Safari打开他们的接口,发现证书不匹配的警告,于是就判定是他们证书配置有问题,后来发现果然是这个问题。
    总结下iOS使用https的问题
    用HTTPS有个问题,就是CA证书。缺省情况下,iOS要求连接的HTTPS站点必须为CA签名过的合法证书,AFNetworking是个iOS上常用的HTTP访问库,由于它是基于iOS的HTTP网络通讯库,自然证书方面的要求和系统是一致的,也就是你需要有一张合法的站点证书。
      正式的CA证书非常昂贵,很多人都知道,AFNetworking2只要通过下面的代码,你就可以使用自签证书来访问HTTPS
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
    securityPolicy.allowInvalidCertificates = YES;
      这么做有个问题,就是你无法验证证书是否是你的服务器后端的证书,给中间人攻击,即通过重定向路由来分析伪造你的服务器端打开了大门。

    浏览器中https验证流程###

    1   客户端输入网址https://www.domain..com,连接到server的443端口。
    2   服务器返回一个证书(包含公钥、和证书信息,如证书的颁发机构,过期时间等),证书由服务器所拥有的私钥非对称加密生成。
    3   客户端对证书进行验证(首先会验证证书是否有效,比如颁发机构,过期时间等等)。
    4   如果客户端验证通过,客户端生成一个随机数,在用服务器返回的证书(公钥)进行加密传输。
    5   因为公钥是通过服务器的私钥生成,所以服务器是可以对客户端的传回的加密数据进行对称解密的。服务器拿到由客户端生成的随机数,对要传递的数据使用随机数加密。
    6   客户端收到服务器使用随机数加密的数据进行解密。
    

    不过在app的开发中因为我们的app通常只需要和一个服务器端进行交互,所以不必要每次请求都从服务器那边获取证书(公钥),在开发中app直接将服务器对应生成的证书(公钥)放在沙盒中,HTTPS请求时只要直接和服务器返回的证书(公钥)进行比对。如果验证通过则使用公钥进行加密在传递回服务器。
    这样即使app中的证书(公钥)被截取,中间人使用证书冒充了服务器与客户端进行通信时(通过了验证),但因为从app返回的数据都是通过证书(公钥)加密的。而中间人从app截取的证书时公钥,缺少对应的私钥即使截获了信息也无法解密。能够最大的程度的保护传递的信息安全。
    从上面的通信过程中,最重要的是存储在服务器的私钥。因为只有私钥生成了在通信过程中传递的证书(公钥),且只有通过私钥才能对公钥加密的信息进行解密,所以在开发过程中保护好私钥的安全。
    代码介绍:

    /**
     SSL身份认证
    
     @return
     */
    + (AFSecurityPolicy *)customSecurityPolicy{
    
        // 导入证书 仅支持cer 格式 需要将crt格式转换下  //转换格式 openssl x509 -in 你的证书.crt -out 你的证书.cer -outform der
        NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"2__.gongfupay.com" ofType:@"cer"];
        NSData *cerData = [NSData dataWithContentsOfFile:cerPath];
        // AFSSLPinningModeCertificate 使用证书验证模式
        // AFSSLPinningModeNone 这个模式表示不做SSL pinning,只跟浏览器一样在系统的信任机构列表里验证服务端返回的证书。若证书是信任机构签发的就会通过,若是自己服务器生成的证书就不会通过。
        // AFSSLPinningModeCertificate 这个模式表示用证书绑定方式验证证书,需要客户端保存有服务端的证书拷贝,这里验证分两步,第一步验证证书的域名有效期等信息,第二步是对比服务端返回的证书跟客户端返回的是否一致。
        // AFSSLPinningModePublicKey 这个模式同样是用证书绑定方式验证,客户端要有服务端的证书拷贝,只是验证时只验证证书里的公钥,不验证证书的有效期等信息。只要公钥是正确的,就能保证通信不会被窃听,因为中间人没有私钥,无法解开通过公钥加密的数据。
        AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
        // allowInvalidCertificates 是否允许无效证书(也就是自建的证书),默认为NO 如果是需要验证自建证书,需要设置为YES
        securityPolicy.allowInvalidCertificates = YES;
    
        //是否需要验证域名,默认为YES
        //假如证书的域名与你请求的域名不一致,需把该项设置为NO;如设成NO的话,即服务器使用其他可信任机构颁发的证书,也可以建立连接,这个非常危险,建议打开。
        //置为NO,主要用于这种情况:客户端请求的是子域名,而证书上的是另外一个域名。因为SSL证书上的域名是独立的,假如证书上注册的域名是www.google.com,那么mail.google.com是无法验证通过的;当然,有钱可以注册通配符的域名*.google.com,但这个还是比较贵的。
        //如置为NO,建议自己添加对应域名的校验逻辑。
        securityPolicy.validatesDomainName = NO;
    
        [securityPolicy setPinnedCertificates:@[cerData]];
        return securityPolicy;
    }
    
    

    AFHTTPSessionManager调用setSecurityPolicy方法 进行身份验证

    相关文章

      网友评论

        本文标题:iOS https

        本文链接:https://www.haomeiwen.com/subject/vwdsuttx.html