【问题标题】:How to make an HTTP or HTTPS request (emphasis on "or")如何发出 HTTP 或 HTTPS 请求(强调“或”)
【发布时间】:2016-04-19 14:06:23
【问题描述】:

我需要调整其他人为使用我编写的 API 而构建的应用程序。在生产环境中,所述应用程序将向具有签名的可信证书的服务器发出 HTTPS 请求。没问题。

但是,我的本地开发服务器没有 SSL 证书(除了我敲掉的自签名证书)。 Android对此抱怨,特别是抛出javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

所以,我需要做两件事之一。

  • 说服 HttpsURLConnection 接受 http:// URL;
  • 说服同一个 HttpsURLConnection 接受返回的自签名证书。

我已经尝试编写自定义 HostnameVerifier(使用始终返回 true 的验证方法),但这并没有帮助我解决问题。

编辑:为了清楚起见,我不能简单地向 HttpsURLConnection 提供一个 http URL,因为我会收到 com.android.okhttp.internal.huc.HttpURLConnectionImpl cannot be cast to javax.net.ssl.HttpsURLConnection 错误。

【问题讨论】:

    标签: java android ssl


    【解决方案1】:

    在没有较低级别的解决方案的情况下,我只是使用了Webb 库。

    【讨论】:

      【解决方案2】:

      几个月前我在做一个项目时也遇到了同样的情况。我有本地服务器用于使用自签名证书进行开发。这是我的 android 代码,它对我有用:

      final HttpsURLConnection https = (HttpsURLConnection) requestedUrl.openConnection();
      
      try {
      
          https.setConnectTimeout(timeout);
          https.setReadTimeout(timeout);
          https.setRequestMethod(method);
      
          if (sslSocketFactory != null) {
              https.setSSLSocketFactory(sslSocketFactory);
          }
      
          https.setHostnameVerifier(new HostnameVerifier() {
              @Override
              public boolean verify(String hostname, SSLSession session) {
                  HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
                  return hv.verify("localhost", session);
              }
          });
      ...
      

      我记得,有一件棘手的事情 - 服务器的自签名证书是为名称“localhost”编写的,但在 android 中,HTTPS 请求是使用 IP 地址发出的,这是导致拒绝服务器证书的问题。

      并加载客户端证书(在我的例子中,它存储在 android 设备上的 .p12 文件中):

      public static SSLContext loadCertificate(String password)
                  throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException,
                  UnrecoverableKeyException, KeyManagementException {
      
              final FileInputStream fis = new FileInputStream(new File(CERT_FILE_DIRECTORY, CERT_FILE_NAME));
      
              final KeyStore keyStore = KeyStore.getInstance("PKCS12");
              keyStore.load(fis, password.toCharArray());
      
              final KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
              kmf.init(keyStore, null);
              final KeyManager[] keyManagers = kmf.getKeyManagers();
              final SSLContext sslContext = SSLContext.getInstance("TLS");
              sslContext.init(keyManagers, new TrustManager[]{new MyTrustManager()}, null);
              return sslContext;
          }
      

      然后清空 MyTrustManager:

      public class MyTrustManager implements X509TrustManager {
      
          @Override
          public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
          }
      
          @Override
          public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
          }
      
          @Override
          public X509Certificate[] getAcceptedIssuers() {
              return new X509Certificate[0];
          }
      }
      

      有了这一切,我能够通过 HTTPS 使用自签名证书连接到我的本地服务器。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-10-06
        • 1970-01-01
        • 1970-01-01
        • 2020-09-29
        • 2013-03-20
        • 2016-12-07
        • 2021-10-10
        相关资源
        最近更新 更多