【问题标题】:Clarification about correctly POSTing via HTTPS SSL (/ TLS?)关于通过 HTTPS SSL(/TLS?)正确发布的说明
【发布时间】:2018-04-24 14:51:12
【问题描述】:

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();

... 这很好用。我找到了this web page,这表明我需要做的就是将我的HttpURLConnection 切换到HttpsURLConnection,一切都应该可以正常工作。

另一方面,在我服务器的 cPanel 上,我发现了一个 Lets Encrypt 部分,它使我能够将证书应用到我的服务器域。

除其他外,设置此设置会生成PEM-Encoded CertificatePEM-Encoded Issuer 证书。

但后来我有点难过。我只是假设我上面的代码更新为使用HttpsURLConnection 有效吗?我怎么知道它在工作。例如,如果我从我的 cPanel 中删除已颁发的证书,那么上面的代码仍然有效...

发布后我发现的事情

如果我将urlString 设为http,它会抛出异常,而如果它是https 地址则不会,所以我猜这很好。

另外,这个this post 表明我在正确的轨道上,因为我没有收到那里建议的任何错误,而且没有人提到这样做是错误的方式。

Of possible interest,实际上指出“SSL 现在称为传输层安全性 (TLS)”,这已经简化了事情。

This looks like a great 文章。我还注意到,除了 Lets Encrypt 选项之外,我们还必须在 cPanel 上设置 SSL/TLS。确实有道理,原来没看到。 更多: 原来 Lets Encrypt 是一项免费服务,它为您提供自动使用的证书,而不是从服务提供商处购买。但是,您也可以签署自己的免费证书,但不会被任何受信任的证书颁发机构 (CA) “认可”。

【问题讨论】:

    标签: java ssl-certificate httpsurlconnection


    【解决方案1】:

    我通常使用如下方法使 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(...){} 
    

    【讨论】:

    • 感谢您的回答。这会在客户端和服务器之间创建安全的 TLS 连接吗?我想我知道你从哪里来。例如。我需要一个我实际支付的证书的唯一原因是如果我有一个基于 Web 的客户端,我希望浏览器将我的网页服务器识别为安全的(出现绿色挂锁)。但事实上,我正在处理移动和桌面应用程序,它们没有现代浏览器的这个警告......
    • ... 这样我就可以签署自己的证书,而无需使用 Lets Encrypt 或从 CA 购买证书...?只要我有一个安全的连接,这就是最重要的。
    • 基本上没问题,如果你有自己的http客户端。我一直在使用我在我的 android 应用程序中提供的代码,但我们有一个带有公共证书的服务器。我也有使用 openssl 自己生成的证书的推送客户端,它仍在工作。
    【解决方案2】:

    好的,经过一整天的工作,我终于解决了这个问题。第一个 SSL 和 TLS 通常意味着相同的想法,TLS 是旧 SSL 的替代品。接下来,要获得安全连接,您需要在服务器上安装证书。这实际上通过 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。

    【讨论】:

      猜你喜欢
      • 2016-11-03
      • 1970-01-01
      • 2018-10-04
      • 2012-04-19
      • 2019-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多