• Https适配


     
     
     
     
     
     
     
     

    https封面

    在WWDC 2016开发者大会上,苹果宣布了一个最后期限:到2017年1月1日 App Store中的所有应用都必须启用 App Transport Security安全功能。也就是说,自2017年起,网络请求必须由http改成https。正因为这个原因,我也打算尝试下适配Https网络请求。由于先前没有配置服务器经验,网上说的也很不详细,因此踩了不少坑,足足花了一天的时间。现在我把我配置的流程写下来,希望后来人能少走点弯路。(网上教程有,但是写得很乱,难理解,这里我打算用最通俗的语言来描述。)

    概念误区:HTTPS和语言无关


    一开始,我以为https应该像处理http报头一样,要写什么PHP代码(服务器语言是PHP),把客户端传来的证书经过处理验证什么的,然后再返回处理结果(类似于Token验证)。因此,一开始我就搜PHP怎么处理HTTPS请求,结果都是介绍怎么用PHP发送HTTPS请求的。经过一段时间纠结,我才意识到HTTPS的处理并不需要PHP做什么,你的服务器(比如apache)就已经帮你做好验证了,你只需要像接收http请求一样处理数据就可以了,也就是说,服务器增加HTTPS并不需要在代码中做什么,只要服务器配置下就好

    关于HTTPS握手流程我觉得还是应该了解下,可以参考这份资料:https握手流程

    简单得说就是客户端向服务器发起需求 ,服务器把证书发给客户端,客户端验证下证书是否合法,然后用证书的数据加密传输数据给服务器,服务器解密

    生成证书文件


    看了上面的原理就知道,要HTTPS传输首先得有证书。在生成证书这方面我也遇到了很大的坑,几乎所有的网站都要生成2个证书,server.pemclient.pem。一开始我把server.pem配置到服务器上,把client.pem给AFNetwoking,结果怎么都通过不了验证!后来我发现只要AFNetworing使用server.pem验证就可以了,也就是说只要一份证书就行了。。。(真的不知道为什么要2份证书,如有大神欢迎指出)。

    下面我将命令行代码贴出来,主要参考这篇文章:参考文章

    //第一步,为服务器端和客户端准备公钥、私钥
    # 生成服务器端私钥
    openssl genrsa -out server.key 1024
    # 生成服务器端公钥
    openssl rsa -in server.key -pubout -out server.pem
    
    //第二步,生成 CA 证书
    # 生成 CA 私钥
    openssl genrsa -out ca.key 1024
    # X.509 Certificate Signing Request (CSR) Management.
    openssl req -new -key ca.key -out ca.csr
    # X.509 Certificate Data Management.
    openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt

    在第二步时会出来一个填写资料的界面(我已经填好大家可以参考,有些地方可以空着)

    Country Name (2 letter code) [AU]:CN
    State or Province Name (full name) [Some-State]:Zhejiang
    Locality Name (eg, city) []:Hangzhou
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:My CA
    Organizational Unit Name (eg, section) []:
    Common Name (e.g. server FQDN or YOUR name) []:localhost
    Email Address []:

    这里有点要注意, Common Name (e.g. server FQDN or YOUR name) []: 这一项,是最后可以访问的域名,我这里为了方便测试,写成 localhost ,如果是为了给网站生成证书,需要写成 xxxx.com 。

    //第三步,生成服务器端证书
    # 服务器端需要向 CA 机构申请签名证书,在申请签名证书之前依然是创建自己的 CSR 文件
    openssl req -new -key server.key -out server.csr
    # 向自己的 CA 机构申请证书,签名过程需要 CA 的证书和私钥参与,最终颁发一个带有 CA 签名的证书
    openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.cr

    同样会有信息填写,照旧写就好了。

    第四步,生成cer文件
    使用openssl 进行转换
    openssl x509 -in server.crt -out server.cer -outform der

    如果完成,就会得到这么多文件


    证书文件

    配置服务器


    为了方便,我是以mac本地电脑做服务器,使用的是XAMPP搭建的服务器使用的是apache。在其他服务器上应该就是文件路径位置不一样,其他应该是一样的。如果有些服务器没开启ssl,可以网上搜索怎么开启。

    修改httpd-ssl.conf文件 把server.crt和server.key的路径修改对就好了
    SSLCertificateFile /apache/conf/server.crt  
    SSLCertificateKeyFile /apache/conf/server.key

    由于我的服务器默认开启ssl,因此我就修改下证书路径就好了。
    我们来浏览器访问下


    浏览器访问https

    按我标出的框来访问证书,就可以看见我们刚才自己填的数据


    服务器返回的证书


    因为不同服务器配置不同,不能一概而论,所以大家还是根据自己服务器的情况再配置。

    配置AFNetworking


    这里直接上代码

    + (AFSecurityPolicy*)customSecurityPolicy
    {
        // /先导入证书
        NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"cer"];//证书的路径
        NSData *certData = [NSData dataWithContentsOfFile:cerPath];
    
        // AFSSLPinningModeCertificate 使用证书验证模式
        AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
    
        // allowInvalidCertificates 是否允许无效证书(也就是自建的证书),默认为NO
        // 如果是需要验证自建证书,需要设置为YES
        securityPolicy.allowInvalidCertificates = YES;
    
        //validatesDomainName 是否需要验证域名,默认为YES;
        //假如证书的域名与你请求的域名不一致,需把该项设置为NO;如设成NO的话,即服务器使用其他可信任机构颁发的证书,也可以建立连接,这个非常危险,建议打开。
        //置为NO,主要用于这种情况:客户端请求的是子域名,而证书上的是另外一个域名。因为SSL证书上的域名是独立的,假如证书上注册的域名是www.google.com,那么mail.google.com是无法验证通过的;当然,有钱可以注册通配符的域名*.google.com,但这个还是比较贵的。
       //如置为NO,建议自己添加对应域名的校验逻辑。
        securityPolicy.validatesDomainName = NO;
    
        securityPolicy.pinnedCertificates = @[certData];
    
        return securityPolicy;
    }
    
    + (void)post:(NSString *)url params:(NSDictionary *)params success:(void (^)(id))success failure:(void (^)(NSError *))failure
    {
        // 1.获得请求管理者
        AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];
        // 2.申明返回的结果是text/html类型
        mgr.responseSerializer = [AFHTTPResponseSerializer serializer];
    
        // 加上这行代码,https ssl 验证。
        [mgr setSecurityPolicy:[NetworkHelpManager customSecurityPolicy]];
    
        // 3.发送POST请求
        [mgr POST:url parameters:params
      success:^(NSURLSessionDataTask *operation, id responseObj) {
              if (success) {
                success(responseObj);
             }
          } failure:^(NSURLSessionDataTask *operation, NSError *error) {
              if (failure) {
                  failure(error);
              }
          }];
    }

    还要记得把证书添加到项目中来哦


    项目中的证书

    下面要介绍下证书的验证模式 AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];

    • AFSSLPinningModeNone 

    不做任何验证,只要服务器返回了证书就通过

    • AFSSLPinningModePublicKey 

    只验证公钥部分,只要公钥部分一致就验证通过,如图所示,红色框起来的部分只要一致就通过


    客户端和服务器端证书对比
    • AFSSLPinningModeCertificate

    除了公钥外,其他能容也要一致才能通过验证。

    配置结果


    下面我们用Charles抓包看看是否成功加密了。


    抓包结果

    返回的数据依稀能看出我们证书里的内容,但是数据已经加密了。

    总结


    配置https其实并不难,既然迟早要更新还不如早一点配置好。其实很多时候都是我们不愿意做,而不是不能做。多一点耐心,多一点实践,就能多一点突破。

    我是翻滚的牛宝宝,欢迎大家评论交流~

  • 相关阅读:
    BPF and eBPF linux
    o-sync-and-o-direct
    linux performance test
    iostat
    MYSQL IO innodb-buffer-pool
    MYSQL file types redo log
    read pread write pwrite open
    CORE DUMP
    linux kernel的中断子系统 softirq
    linux KERNEL 问题
  • 原文地址:https://www.cnblogs.com/isItOk/p/6582979.html
Copyright © 2020-2023  润新知