设置https.protocols系统属性时出现问题,用于HTTPS连接。

7

我有一个Java实现,被各种客户端应用程序用于连接到第三方系统。这些第三方系统支持通过http / https的不同协议。在这种情况下,所有客户端应用程序都托管在我的Java实现托管的同一台服务器上。因此,在这种情况下,各种客户端应用程序将各种https协议设置为系统属性(例如:System.setProperty("https.protocols", "SSLv3")System.setProperty("https.protocols", "TLS")),当他们使用它来连接到那些第三方系统时。

在这里,系统属性在该环境中共享。因此,修改系统属性会导致许多问题。所以,我想知道:

  1. 是否有任何方法可以在不使用系统属性的情况下完成此操作?
  2. 是否有任何方法可以设置所有可能的https.protocols,以便它支持对第三方系统支持的各种协议进行的任何http或https连接?

每个JDK版本支持的协议和算法如blogs.oracle.com所述:

enter image description here

代码:

String responseStr = null;

System.setProperty("https.protocols",http-protocol); // This is set by the client applications. Previously, there was one by one (eg : "SSLv3". Then I changed it to "TLSv1.2,TLSv1.1,TLSv1,SSLv3" assuming it will enable all) 

byteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byteArrayOutputStream.write(requestStr.getBytes());

URL mUrl = new URL(proxy_url);
HttpURLConnection con = (HttpURLConnection) mUrl.openConnection(); // It works fine for the HttpURLConnection when there's no (s)

con.setRequestMethod("POST");
con.setDoOutput(true);
con.setUseCaches(false);
con.setDoInput(true);

con.setRequestProperty("user-agent","Mozilla(MSIE)");
con.setRequestProperty("Accept-Encoding","gzip,deflate");

byteArrayOutputStream.writeTo(con.getOutputStream());

String encodingHeader = con.getHeaderField("Content-Encoding");
InputStream inputStream = null;

if(encodingHeader != null && encodingHeader.toLowerCase().indexOf("gzip") != -1){
    inputStream = new GZIPInputStream(con.getInputStream());
}else {
    inputStream = con.getInputStream();

}

if (inputStream != null) {

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
       byte[] buffer = new byte[4096];
       int length = 0;

       while ((length = inputStream.read(buffer)) != -1) {
           baos.write(buffer, 0, length);
       }

    responseStr = new String(baos.toByteArray());
    baos.close();

 }

我的Java版本:1.5


1
你需要升级。1.5版本已经发布十年了。 - user207421
1
这是非常正确的。但现在有一个很大的变通方法。因此,我正在寻找当前版本的解决方案。 - ironwood
1
这个问题的答案可能是相关的: https://superuser.com/questions/747377/enable-tls-1-1-and-1-2-for-clients-on-java-7 值得注意的是,Oracle文档显示,虽然Java 1.7支持TLS1.2,但默认情况下禁用客户端连接。 - BryKKan
ByteArrayOutputStream在这里是浪费时间和空间。 - user207421
如何启用JAVA 7中未启用的协议?(我不想强制使用它们...只是启用它们)。这是正确的方法吗?System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2"); - marcolopes
1
@marcolopes 这些协议要么启用,要么完全不存在。无论设置系统属性的数量如何,都无法改变这一点。 - user207421
1个回答

0

我建议您不设置它。只需让系统与同行协商。它将协商出最强的共享协议。


它协商双方共同支持的最高协议。我已经说过了。如果你的Java版本不支持对等方所需的内容,无论设置系统属性多少也无济于事。 - user207421
这正是我所说的。如果同行需要比您的Java支持的更高版本,则肯定会遇到问题,但这与提及系统属性无关。如果您需要TLS 1.2支持,则唯一的选择是升级Java版本。 - user207421
2
我理解你的意思。但是考虑这样一种情况,我有一个名为“x”的客户端应用程序和另一个名为“y”的客户端应用程序使用我的实现。假设我的Java版本是1.7。应用程序x需要TLSv1.2才能连接第三方,因此,如果没有指定协议,它将无法连接,因为JAVA 1.7的默认值是TLSv1。当我们将http.protocols设置为TLSv1.2时,它可以正常工作。但是它会影响到其他需要使用另一种协议连接的客户端应用程序“y”。如果我们不指定https.protocol,它会使用默认的协议,而不是最佳的协议。 - ironwood
1
我在问题中更新了每个JDK版本所支持的协议和算法,如blogs.oracle.com所述。 - ironwood
1
我正在使用支持(TLS1,TLS1.1,TLS1.2和SSLv3)的Java 1.7。在客户端启用SSL调试后,我发现以下内容:“*** ClientHello,TLSv1”。根据您的回答,我们可以说服务器端可用的最强协议是TLS1.0吗? - Salman
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接