Использование Httpsurlconnection для подключения к серверу (SSL) - PullRequest
0 голосов
/ 04 июля 2018

Я пытался перейти от самозаверяющего сертификата к хорошо известному центру сертификации (от Let's Encrypted). Исходный код, приведенный ниже, хорошо работает для подключения приложения Android к серверу, сначала передав JSON, например. {"name": "xxx"}, а сервер отображает соответствующие данные.

 try {

      URL url = new URL(intent.getStringExtra(URL));
      HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
      conn.setSSLSocketFactory(buildSslSocketFactory());
      conn.setConnectTimeout(15000);
      conn.setRequestMethod("POST");
      conn.setDoInput(true);
      conn.setDoOutput(true);
      conn.setChunkedStreamingMode(0);
      conn.setRequestProperty("Accept", "application/json");
      conn.setRequestProperty("Content-Type", "application/json");
      conn.connect();
      OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
      Log.d(TAG,data +"sending to " + actStr(action) );
      writer.write(data);
      writer.close();
      int respC = conn.getResponseCode();
      if (respC < 200 || respC >= 400 ) { // OK is 200-399
          Log.e(TAG, "sending to " + actStr(action) + ", got response code " + respC + "=" + conn.getResponseMessage());
          conn.disconnect();
          return;
      }
      reader = new BufferedReader( new InputStreamReader( conn.getInputStream()));
      makeStr = new StringBuilder();
      data = "";
      while ((data = reader.readLine()) != null) {
            makeStr.append(data);
            Log.d(TAG, "read"+data);
      }
      conn.disconnect();
 } catch (Exception e) {
      Log.d(TAG, "Failed sending to " + actStr(action) + ", cause: " + e.getCause() + " message: " + e.getMessage());
 } finally {
      if (reader != null) {
          try {
               makeStr.append("");
               reader.close();
          } catch (IOException ioe) {
                ioe.printStackTrace();
          }
       }
 }

Он поставляется вместе со стандартным SslSocketFactory:

private static SSLSocketFactory buildSslSocketFactory() {
    // Add support for self-signed (local) SSL certificates
    // Based on http://developer.android.com/training/articles/security-ssl.html#UnknownCa
    try {

        // Load CAs from an InputStream
        // (could be from a resource or ByteArrayInputStream or ...)
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        // From https://www.washington.edu/itconnect/security/ca/load-der.crt
        InputStream is = App.getAppResources().getAssets().open(ManageActivity.certificate);
        InputStream caInput = new BufferedInputStream(is);
        Certificate ca;
        try {
            ca = cf.generateCertificate(caInput);
            //System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
            Log.d(TAG,"ca=" +((X509Certificate) ca).getSubjectDN());
        } finally {
            caInput.close();
        }

        // Create a KeyStore containing our trusted CAs
        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        // Create a TrustManager that trusts the CAs in our KeyStore
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

        // Create an SSLContext that uses our TrustManager
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, tmf.getTrustManagers(), null);
        return sslContext.getSocketFactory();

    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (KeyManagementException e) {
        e.printStackTrace();
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;

}

Итак, чтобы перейти на сайт с доверенным сертификатом, я оставляю приведенный выше код таким же, но меняю сертификат, который является crt с комбинацией промежуточного сертификата + сертификата сайта в соответствии с ответом nKn: Android : как сделать HttpPost с сертификатом (я на самом деле пробовал все комбинации среди корневых, промежуточных и сертификатов сайта, и тестировал отдельные сертификаты отдельно. Но ни один из них не работал). В отличие от вопросов других, я не получаю никаких ошибок, говоря, что у меня есть недоверенный сертификат или что-то в этом роде.

С сайта сервера, кажется, получен запрос на публикацию (я получил сообщение из журнала ошибок), но на входе ничего нет, и поэтому приложение также не получает ответа от сервера. Однако по сравнению с настройкой самозаверяющего сертификата коды с сайта сервера полностью совпадают, плюс, когда я передаю тот же JSON из терминала с помощью curl, он отвечает тем, что я хочу, поэтому я сомневаюсь, что это проблема с сертификатом.

Кто-нибудь знает, как ее решить, или мне на самом деле не нужно включать сертификат или что-то?

1 Ответ

0 голосов
/ 05 июля 2018

Итак, я обнаружил, в чем проблема в конце. наверное линия

conn.setChunkedStreamingMode(0);

не позволяет передавать данные на сервер (хотя я не знаю, почему это работает, когда я раньше использовал самозаверяющий сертификат ...)

Кроме того, SslSocketFactory в этом случае не требуется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...