• App校验https证书


    对App进行全面的安全性测试的时候,发现虽然用的https证书,但是也同时开启了允许任意http链接,导致检测的时候提示不安全

    1. 安卓HttpsURLConnection使用证书

      //HttpsURLConnection
      private static void setCertificate(HttpsURLConnection connection) {
          InputStream caInput = null;
          try {
              CertificateFactory cf = CertificateFactory.getInstance("X.509");
              caInput = MyApplication.mContext.getAssets().open("sguClass.cer");
              Certificate ca = cf.generateCertificate(caInput);
              String keyStoreType = KeyStore.getDefaultType();
              KeyStore keyStore = KeyStore.getInstance(keyStoreType);
              keyStore.load(null, null);
              keyStore.setCertificateEntry("ca", ca);
      
              String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
              TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
              tmf.init(keyStore);
      
              SSLContext context = SSLContext.getInstance("TLS");
              context.init(null, tmf.getTrustManagers(), null);
              connection.setSSLSocketFactory(context.getSocketFactory());
              connection.setHostnameVerifier(new HostnameVerifier() {
                  @Override
                  public boolean verify(String s, SSLSession sslSession) {
                      return true;
                  }
              });
          } catch (CertificateException | IOException | KeyStoreException | NoSuchAlgorithmException | KeyManagementException e) {
              e.printStackTrace();
          } finally {
              try {
                  caInput.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }
      
    2. 安卓WebView使用证书

              //Webview
              public void onReceivedSslError(WebView webView, SslErrorHandler sslErrorHandler, SslError sslError) {
      //            super.onReceivedSslError(webView, sslErrorHandler, sslError);//sslErrorHandler.cancel();
      //            sslErrorHandler.proceed();
      
                  if (chkMySSLCNCert(sslError.getCertificate())) {{//结果应该都是false,有问题的话取消验证
                      sslErrorHandler.proceed();
                  } else {
                      sslErrorHandler.cancel();
                  }
      
      //            if (sslError.getPrimaryError() == android.net.http.SslError.SSL_DATE_INVALID  // 日期不正确
      //                    || sslError.getPrimaryError() == android.net.http.SslError.SSL_EXPIRED // 日期不正确
      //                    || sslError.getPrimaryError() == android.net.http.SslError.SSL_INVALID // webview BUG
      //                    || sslError.getPrimaryError() == android.net.http.SslError.SSL_UNTRUSTED) { // 根证书丢失
      //                if (chkMySSLCNCert(sslError.getCertificate())) {
      //                    sslErrorHandler.proceed();  // 如果证书一致,忽略错误
      //                }
      //            }
              }
          private static boolean chkMySSLCNCert(SslCertificate cert) {
              try {
                  //本地证书
                  CertificateFactory cf = CertificateFactory.getInstance("X.509");
                  InputStream caInput = MyApplication.mContext.getAssets().open("sguClass.cer");
                  Certificate ca = cf.generateCertificate(caInput);
                  MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
                  byte[] caKey = sha256.digest(ca.getEncoded());
      
                  //服务端证书
                  Bundle bundle = SslCertificate.saveState(cert);
                  byte[] bytes = bundle.getByteArray("x509-certificate");
                  Certificate certificate = cf.generateCertificate(new ByteArrayInputStream(bytes));;
                  byte[] certificateKey = sha256.digest(certificate.getEncoded());
                  Log.d("test", "chkMySSLCNCert" + "caKey:" + caKey + " certificateKey: " + certificateKey);
                  return Arrays.equals(caKey, certificateKey);
              } catch (CertificateException | IOException | NoSuchAlgorithmException e) {
                  e.printStackTrace();
              }
      
              return false;
          }
      
    3. iOS afnetworking添加证书

      //AFNetworking
      AFHTTPSessionManager *manager = [[AFHTTPSessionManager manager] initWithBaseURL:[NSURL URLWithString:BASE_URL_API]];
      manager.securityPolicy = [self customSecurityPolicy];
      + (AFSecurityPolicy *)customSecurityPolicy {
          NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"sguClass" ofType:@"cer"];//证书的路径
          NSData *cerData = [NSData dataWithContentsOfFile:cerPath];
          AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
          securityPolicy.allowInvalidCertificates = NO;//是否允许无效证书
          if (cerData) {
              securityPolicy.pinnedCertificates = [NSSet setWithObject:cerData];
          }
          return securityPolicy;
      }
      
    4. iOS WKWebView添加证书

      //WKWebview
      //Allow Arbitrary Loads in Web Content设置为YES防止外部http链接打不开
      - (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
          NSLog(@"didReceiveAuthenticationChallenge");
          //1.信任所有证书
      //    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
      //        NSURLCredential *credential = [[NSURLCredential alloc] initWithTrust:challenge.protectionSpace.serverTrust];
      //        completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
      //    }
          
          //2.比较证书内容,相同的在信任 //强限制,部分部分外部资源加载不了
          SecTrustRef trust = challenge.protectionSpace.serverTrust;
          // 从信任链返回一个证书
          SecCertificateRef serverCer= SecTrustGetCertificateAtIndex(trust, 0);
          // SecCertificateCopyData 返回X.509证书的DER表示
          NSData *serverCerData = CFBridgingRelease(SecCertificateCopyData(serverCer));
          NSString *localCerPath = [[NSBundle mainBundle] pathForResource:@"sguClass" ofType:@"cer"];
          NSData *localCerData = [NSData dataWithContentsOfFile:localCerPath];
          if ([serverCerData isEqualToData:localCerData]) {
              NSURLCredential *credential = [[NSURLCredential alloc] initWithTrust:trust];
              [challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
              completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
              NSLog(@"服务端证书认证成功");
          } else {
              completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, NULL);
              NSLog(@"服务端证书认证失败");
          }
      }
      

    添加完证书之后,发现会有一些问题,主要是外部http资源和第三方http链接无法访问,所以有去掉了部分验证。如果项目没有用到这些内容,还是可以添加的,更安全一些。

  • 相关阅读:
    【底层原理】四位计算机的原理及其实现
    ctags的如何生成tags文件
    nginx-1.12.0版本(编译安装)-自定义安装路径
    使用LVS实现负载均衡原理及安装配置详解
    【系统架构】亿级Web系统搭建(1):Web负载均衡
    9个Linux系统常用监控命令
    NetStat命令详解
    SQLSERVER CXPACKET 等待
    什么是PAGELATCH和PAGEIOLATCH
    CentOS环境变量配置并生效
  • 原文地址:https://www.cnblogs.com/shenyuiOS/p/16036881.html
Copyright © 2020-2023  润新知