Разъяснение о правильной POSTing через HTTPS SSL (/ TLS?) - PullRequest
0 голосов
/ 24 апреля 2018

Всего новичков в SSL. Я знаю, что должен использовать HTTPS SSL (/ TLS?) Для отправки моих данных на мой сервер из моего клиентского приложения. Или, по крайней мере, это то, что я хочу сделать.

Моя предыдущая реализация в Java использовала HttpURLConnection и выглядела примерно так:

    HttpURLConnection conn = null;

    try
    {
        URL url = new URL(urlString);
        conn = (HttpURLConnection) url.openConnection();
        conn.setDoOutput(true);
        conn.setRequestMethod("POST");
        OutputStream os = conn.getOutputStream();
        OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
        osw.write(dataString);
        osw.flush();
        osw.close();
        os.close();
        conn.connect();

        if(conn.getResponseCode() != 200)
            throw new MyServerException();

        BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
        String output;
        StringBuilder sb = new StringBuilder();

        while ((output = br.readLine()) != null) {
            sb.append(output);
        }

        if(conn != null)
            conn.disconnect();

        return sb.toString();
    }
    catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    catch (ProtocolException e) {
        e.printStackTrace();
    }
    catch (MalformedURLException e) {
        e.printStackTrace();
    }
    catch (IOException e) {
        e.printStackTrace();
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    finally {
        if(conn != null)
            conn.disconnect();
    }

    throw new MyServerException();

... и это прекрасно работает. Я нашел эту веб-страницу , которая предлагает все, что мне нужно сделать, это переключить мой HttpURLConnection на HttpsURLConnection, и все должно работать нормально.

С другой стороны, на cPanel моего сервера я обнаружил раздел Lets Encrypt, который позволял мне применять сертификаты к доменам моего сервера.

Установка этого параметра, среди прочего, дает сертификаты PEM-Encoded Certificate и PEM-Encoded Issuer.

Но тогда я немного озадачен. Я просто предполагаю, что мой код, обновленный для использования HttpsURLConnection, работает? Как я знаю, что это работает. Например, если я удаляю выданные сертификаты из моей cPanel, приведенный выше код все еще работает ...

Вещи, которые я узнал с момента публикации

Если я сделаю свой urlString a http, он выдаст и исключение, тогда как если это адрес https, то нет, так что это хорошо, я думаю.

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

Возможный интерес , который фактически указывает на то, что «SSL теперь называется Transport Layer Security (TLS)», что уже упрощает вещи.

Это похоже на отличную статью . Я также заметил, что здесь упоминается, что мы должны настроить SSL / TLS и на cPanel, в дополнение к опции Lets Encrypt. Имеет смысл на самом деле, не видел этого изначально. Подробнее: Оказывается, Lets Encrypt - это бесплатная услуга, которая предоставляет вам автоматический сертификат для использования, а не покупает его у поставщика услуг. Однако вы также можете подписать свои собственные сертификаты, которые бесплатны, но затем не «распознаны» ни одним доверенным центром сертификации (CA).

Ответы [ 2 ]

0 голосов
/ 25 апреля 2018

Хорошо, я наконец решил это после целого дня.Первые SSL и TLS обычно означают одно и то же, с заменой старого SSL на TLS.Далее, чтобы получить безопасное соединение, вам нужно установить сертификат на вашем сервере.Это на самом деле очень легко с помощью cPanel.На самом деле я рекомендую использовать Lets Encrypt, который предлагает бесплатные сертификаты, которые действуют 90 дней.Вы можете автоматически обновить свою сторону сервера сертификатов, настроив задание crontab, так что они не только бесплатны, но и бессрочны.

После настройки сертификата вы можете установить безопасное соединение и POST, используяследующий код:

    SSLContext sc = null;
    HttpsURLConnection conn = null;

    try {
        URL httpsURL = new URL(urlString);
        sc = SSLContext.getInstance("TLSv1.2");
        sc.init(null, null, new java.security.SecureRandom());
        conn  = (HttpsURLConnection) httpsURL.openConnection();
        conn.setSSLSocketFactory(sc.getSocketFactory());

        conn.setDoOutput(true);
        conn.setRequestMethod("POST");
        OutputStream os = conn.getOutputStream();
        OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
        osw.write(dataString);
        osw.flush();
        osw.close();
        os.close();
        conn.connect();

        if(conn.getResponseCode() != 200)
            throw new MyServerException();

        BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
        String output;
        StringBuilder sb = new StringBuilder();

        while ((output = br.readLine()) != null) {
            sb.append(output);
        }

        if(conn != null)
            conn.disconnect();

        return sb.toString();
    }
    catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    catch (KeyManagementException e) {
        e.printStackTrace();
    }
    catch (MalformedURLException e) {
        e.printStackTrace();
    }
    catch (IOException e) {
        e.printStackTrace();
    }

    if(conn != null)
        conn.disconnect();

    throw new MyServerException();

Красиво и просто на самом деле.Возможно, мне также нужен какой-нибудь верификатор имени хоста, такой как @tommybee, упомянутый в его ответе.

0 голосов
/ 24 апреля 2018

Я обычно использовал такой метод, как сделать так, чтобы соединение https url доверяло любому сертификату, следующим образом.

try {
    SSLContext context = SSLContext.getInstance("TLS");
    context.init(null, new X509TrustManager[]{new X509TrustManager() {
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
    }}, new SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
} catch(NoSuchAlgorithmException e) {
    e.printStackTrace();
} catch(KeyManagementException e) {
    e.printStackTrace();
}

И делал безопасный запрос к серверу с сертификатами, которые не имеют имени хоста.

HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
    @Override
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }
});

Затем вы можете получить объект HttpURLConnection как объект HttpsURLConnection.

HttpURLConnection connection = null;
try
{
    URL _url = new URL(url);
    String scheme = _url.getProtocol();

    if(scheme.equals("https")) {
       connection = (HttpsURLConnection)new URL(url).openConnection();
    }
 }catch(...){} 
...