zoukankan      html  css  js  c++  java
  • HTTPS

     

    我们先来看一下百度百科的解释:
    HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 它是一个URI scheme(抽象标识符体系),句法类同http:体系。用于安全的HTTP数据传输。https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。这个系统的最初研发由网景公司(Netscape)进行,并内置于其浏览器Netscape Navigator中,提供了身份验证与加密通讯方法

    简单来讲就是一句话: HTTP + SSL = HTTPS

    那 HTTP 和 HTTPS 二者之间到底有什么区别呢 ?
    HTTP(超文本传输协议)协议被用于在Web浏览器和网站服务器之间传递信息。HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息,因此HTTP协议不适合传输一些敏感信息,比如信用卡号、密码等。
    为了解决HTTP协议的这一缺陷,需要使用另一种协议:安全套接字层超文本传输协议HTTPS。为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。

    HTTPS和HTTP的区别主要为以下四点:
    一、https协议需要到ca申请证书,一般免费证书很少,需要交费。
    二、http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。
    三、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
    四、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

    那现在肯定有些人对SSL好奇咯,我们现在看看 SSL能提供一些什么服务呢 ?

    SSL协议提供的服务主要有哪些
    1)认证用户和服务器,确保数据发送到正确的客户机和服务器
    2)加密数据以防止数据中途被窃取
    3)维护数据的完整性,确保数据在传输过程中不被改变。
    SSL协议的工作流程
    服务器认证阶段:
    1)客户端向服务器发送一个开始信息“Hello”以便开始一个新的会话连接;
    2)服务器根据客户的信息确定是否需要生成新的主密钥,如需要则服务器在响应客户的“Hello”信息时将包含生成主密钥所需的信息;
    3)客户根据收到的服务器响应信息,产生一个主密钥,并用服务器的公开密钥加密后传给服务器;
    4)服务器恢复该主密钥,并返回给客户一个用主密钥认证的信息,以此让客户认证服务器。

    那 现在我们来看一下 HTTPS 在使用时 我们在iOS这一块需要做一些什么事情呢 ?

    实现支持HTTPS
    首先,需要明确你使用HTTP/HTTPS的用途,因为OSX和iOS平台提供了多种API,来支持不同的用途,官方文档《Making HTTP and HTTPS Requests》有详细的说明,而文档《HTTPS Server Trust Evaluation》则详细讲解了HTTPS验证相关知识,这里就不多说了。本文主要讲解我们最常用的NSURLConnection支持HTTPS的实现(NSURLSession的实现方法类似,只是要求授权证明的回调不一样而已),以及怎么样使用AFNetworking这个非常流行的第三方库来支持HTTPS。本文假设你对HTTP以及NSURLConnection的接口有了足够的了解。
    验证证书的API
    相关的Api在Security Framework中,验证流程如下:
    1). 第一步,先获取需要验证的信任对象(Trust Object)。这个Trust Object在不同的应用场景下获取的方式都不一样,对于NSURLConnection来说,是从delegate方法-connection:willSendRequestForAuthenticationChallenge:回调回来的参数challenge中获取([challenge.protectionSpace serverTrust])。
    2). 使用系统默认验证方式验证Trust Object。SecTrustEvaluate会根据Trust Object的验证策略,一级一级往上,验证证书链上每一级数字签名的有效性(上一部分有讲解),从而评估证书的有效性。
    3). 如第二步验证通过了,一般的安全要求下,就可以直接验证通过,进入到下一步:使用Trust Object生成一份凭证([NSURLCredential credentialForTrust:serverTrust]),传入challenge的sender中([challenge.sender useCredential:cred forAuthenticationChallenge:challenge])处理,建立连接。
    4). 假如有更强的安全要求,可以继续对Trust Object进行更严格的验证。常用的方式是在本地导入证书,验证Trust Object与导入的证书是否匹配。更多的方法可以查看Enforcing Stricter Server Trust Evaluation,这一部分在讲解AFNetworking源码中会讲解到。
    5). 假如验证失败,取消此次Challenge-Response Authentication验证流程,拒绝连接请求。
    ps: 假如是自建证书的,则会跳过第二步,使用第三部进行验证,因为自建证书的根CA的数字签名未在操作系统的信任列表中。
    iOS授权验证的API和流程大概了解了,下面,我们看看在NSURLConnection中的代码实现:
    使用NSURLConnection支持HTTPS的实现
    // Now start the connection
    NSURL * httpsURL = [NSURL URLWithString:@”https://www.google.com“];
    self.connection = [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:httpsURL] delegate:self];

    //回调

    • (void)connection:(NSURLConnection )connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge )challenge {
      //1)获取trust object
      SecTrustRef trust = challenge.protectionSpace.serverTrust;
      SecTrustResultType result;

      //2)SecTrustEvaluate对trust进行验证
      OSStatus status = SecTrustEvaluate(trust, &result);
      if (status == errSecSuccess &&

      (result == kSecTrustResultProceed ||
      result == kSecTrustResultUnspecified)) {
      
      //3)验证成功,生成NSURLCredential凭证cred,告知challenge的sender使用这个凭证来继续连接
      NSURLCredential *cred = [NSURLCredential credentialForTrust:trust];
      [challenge.sender useCredential:cred forAuthenticationChallenge:challenge];
      

      } else {

      //5)验证失败,取消这次验证流程
      [challenge.sender cancelAuthenticationChallenge:challenge];
      

      }
      }
      上面是代码是通过系统默认验证流程来验证证书的。假如我们是自建证书的呢?这样Trust Object里面服务器的证书因为不是可信任的CA签发的,所以直接使用SecTrustEvaluate进行验证是不会成功。又或者,即使服务器返回的证书是信任CA签发的,又如何确定这证书就是我们想要的特定证书?这就需要先在本地导入证书,设置成需要验证的Anchor Certificate(就是根证书),再调用SecTrustEvaluate来验证。代码如下
      //先导入证书
      NSString cerPath = …; //证书的路径
      NSData 
      cerData = [NSData dataWithContentsOfFile:cerPath];
      SecCertificateRef certificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(cerData));
      self.trustedCertificates = @[CFBridgingRelease(certificate)];
      //回调

    • (void)connection:(NSURLConnection )connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge )challenge {
      //1)获取trust object
      SecTrustRef trust = challenge.protectionSpace.serverTrust;
      SecTrustResultType result;
      //注意:这里将之前导入的证书设置成下面验证的Trust Object的anchor certificate
      SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)self.trustedCertificates);
      //2)SecTrustEvaluate会查找前面SecTrustSetAnchorCertificates设置的证书或者系统默认提供的证书,对trust进行验证
      OSStatus status = SecTrustEvaluate(trust, &result);
      if (status == errSecSuccess &&

      (result == kSecTrustResultProceed ||
      result == kSecTrustResultUnspecified)) {
      
      //3)验证成功,生成NSURLCredential凭证cred,告知challenge的sender使用这个凭证来继续连接
      NSURLCredential *cred = [NSURLCredential credentialForTrust:trust];
      [challenge.sender useCredential:cred forAuthenticationChallenge:challenge];
      

      } else {

      //5)验证失败,取消这次验证流程
      [challenge.sender cancelAuthenticationChallenge:challenge];
      

      }
      }
      建议采用本地导入证书的方式验证证书,来保证足够的安全性。更多的验证方法,请查看官方文档《HTTPS Server Trust Evaluation》

    那 对于熟悉网络请求的同学 对于AFNetworking肯定不会陌生了,它是使用的时候是怎么配置HTTPS的呢?

    AFNetworking上配置对HTTPS的支持非常简单:

    NSURL url = [NSURL URLWithString:@”https://www.google.com“];
    AFHTTPRequestOperationManager 
    requestOperationManager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:url];
    dispatch_queue_t requestQueue = dispatch_create_serial_queue_for_name(“kRequestCompletionQueue”);
    requestOperationManager.completionQueue = requestQueue;
    AFSecurityPolicy securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
    //allowInvalidCertificates 是否允许无效证书(也就是自建的证书),默认为NO
    //如果是需要验证自建证书,需要设置为YES
    securityPolicy.allowInvalidCertificates = YES;
    //validatesDomainName 是否需要验证域名,默认为YES;
    //假如证书的域名与你请求的域名不一致,需把该项设置为NO
    //主要用于这种情况:客户端请求的是子域名,而证书上的是另外一个域名。因为SSL证书上的域名是独立的,假如证书上注册的域名是www.google.com,那么mail.google.com是无法验证通过的;当然,有钱可以注册通配符的域名
    .google.com,但这个还是比较贵的。
    securityPolicy.validatesDomainName = NO;
    //validatesCertificateChain 是否验证整个证书链,默认为YES
    //设置为YES,会将服务器返回的Trust Object上的证书链与本地导入的证书进行对比,这就意味着,假如你的证书链是这样的:
    //GeoTrust Global CA
    // Google Internet Authority G2
    //  .google.com
    //那么,除了导入
    .google.com之外,还需要导入证书链上所有的CA证书(GeoTrust Global CA, Google Internet Authority G2);
    //如是自建证书的时候,可以设置为YES,增强安全性;假如是信任的CA所签发的证书,则建议关闭该验证;
    securityPolicy.validatesCertificateChain = NO;
    requestOperationManager.securityPolicy = securityPolicy;
    这就是AFNetworking的支持HTTPS的主要配置说明,AFHTTPSessionManager与之基本一致,就不重复了。

    因为HTTPS相比于HTTP来说,会有一些性能上的劣势,但是相对比安全性,就是小巫见大巫了。

    最怕你一生碌碌无为 还安慰自己平凡可贵
  • 相关阅读:
    Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis.
    DHCP "No subnet declaration for xxx (no IPv4 addresses)" 报错
    Centos安装前端开发常用软件
    kubernetes学习笔记之十:RBAC(二)
    k8s学习笔记之StorageClass+NFS
    k8s学习笔记之ConfigMap和Secret
    k8s笔记之chartmuseum搭建
    K8S集群集成harbor(1.9.3)服务并配置HTTPS
    Docker镜像仓库Harbor1.7.0搭建及配置
    Nginx自建SSL证书部署HTTPS网站
  • 原文地址:https://www.cnblogs.com/fakeCoder/p/5093810.html
Copyright © 2011-2022 走看看