峰回路转之HTTPS

2020-03-06  本文已影响0人  lmfei

自iOS 9以后,苹果发出强制使用HTTPS协议的规定,虽然到现在也还没有强制实行,不过大多数用户早已使用HTTPS协议替换原有的HTTP协议。相对HTTP,HTTPS更安全,它是在tcp/ip层加入了SSL/TSL加密层。HTTPS的作用是防止中间人攻击的,下面我们来看下有关HTTPS的一些tip

首先我们先来了解下在HTTPS下客户端与服务端之间的一个交互流程:

  1. 客户端发送SSL版本信息、random-c、加密算法至服务端
  2. 服务端发送SSL版本、随机数random-s等信息及服务器公钥至客户端- 非对称加密,耗时,性能低
  3. 客户端校验证书是否合法,合法继续,否则警告
  4. 服务端选择加密程度高的加密方式
  5. 将选择好的加密方式明文发送给客户端
  6. 客户端收到加密方式后,产生随机码(Pre-master),作为加密对称密钥,使用公钥加密后,发给服务端
  7. 服务端使用私钥解密,获得对称加密的密钥
  8. 使用随机码对称加密,进行通讯

上述交互流程中,与客户端密切相关的就是证书校验部分,下面我们来具体看下这个部分的代码实现

首先看下几个重要的类及属性

有了上面的了解,我们就更容易看明白下面代码实现

自签名证书单向校验

针对NSURLConnection的适配
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{

    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]){
    
        [[challenge sender]  useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
        
        [[challenge sender]  continueWithoutCredentialForAuthenticationChallenge: challenge];
    }
}
针对NSURLSession适配
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler
{
    NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
    __block NSURLCredential *credential = nil;
    // 判断返回的证书是否是服务器所信任的
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
    {
        credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
        if (credential)
        {
            //使用返回的证书
            disposition = NSURLSessionAuthChallengeUseCredential; 
        }
        else
        {
            //忽略证书
            disposition = NSURLSessionAuthChallengePerformDefaultHandling; 
        }
    }
    else
    {
        //取消请求
        disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge; 
    }
    //安装证书
    if (completionHandler)   {
        completionHandler(disposition, credential);
    }
}

证书预置本地的单向校验

针对URLSession进行说明

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler
{
      SecTrustRef trustRef = challenge.protectionSpace.serverTrust;
      SecCertificateRef certificateRef = SecTrustGetCertificateAtIndex(servertrust, 0);
      NSData *certidata = CFBridgingRelease(CFBridgingRetain(CFBridgingRelease(SecCertificateCopyData(certificateRef))));
      NSString *path = [[NSBundle mainBundle] pathForResource:@"证书名称" ofType:@"cer"];
  //    NSLog(@"证书 : %@",path);
      NSData *localCertiData = [NSData dataWithContentsOfFile:path];
      if ([certidata isEqualToData:localCertiData]) {
          NSURLCredential *credential = [[NSURLCredential alloc] initWithTrust:servertrust];
          [challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
          completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
  //        NSLog(@"服务端证书认证通过");
      }else {
          completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
          NSLog(@"服务端认证失败");
      }

}

至此,HTTPS的记录就到此结束了。

生活如此美好,今天就点到为止。。。

上一篇下一篇

猜你喜欢

热点阅读