zoukankan      html  css  js  c++  java
  • 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其实并不难,既然迟早要更新还不如早一点配置好。其实很多时候都是我们不愿意做,而不是不能做。多一点耐心,多一点实践,就能多一点突破。

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

  • 相关阅读:
    C#
    C#
    ssh学习笔记
    (已解决)Could not open '/var/lib/nova/mnt/*/volume-*': Permission denied
    RPCVersionCapError: Requested message version, 4.17 is incompatible. It needs to be equal in major version and less than or equal in minor version as the specified version cap 4.11.
    如何在linux下安装idea
    The system has no LUN copy license
    调整mysql数据库最大连接数
    mysql数据库编码问题
    cinder支持nfs快照
  • 原文地址:https://www.cnblogs.com/isItOk/p/6582979.html
Copyright © 2011-2022 走看看