Java 7 Oracle不支持TLSv1.2。

3

Java 7 Oracle不支持TLSv1.2。我一直在尝试运行我的代码,已经尝试了以下几个方案:

    System.setProperty("deployment.security.TLSv1.1", "false")
    System.setProperty("deployment.security.TLSv1", "false")
    System.setProperty("deployment.security.TLSv1.2", "true")
    System.setProperty("https.protocols", "TLSv1.2")
    System.setProperty("https.cipherSuites", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,AES_256_GCM,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384")

这并没有什么用。

我该如何强制我的Java7应用程序使用Tlsv1.2。我可以使用默认情况下使用TLS1.2的java8来运行程序,一切工作得很完美。

我该如何在oracle的Java7中做到这一点。

我也尝试进入/usr/lib/jvm/java-7-oracle/jre/lib/security并禁用jdk.tls.disabledAlgorithms=SSLv2Hello, SSLv3, TLSv1,但仍然无法正常工作。

我做错了什么吗?

顺便说一句,我得到了sslhandshakeexception-handshake-failure

编辑:

错误:

0000: 02 28                                              .(
main, READ: TLSv1 Alert, length = 2
main, RECV TLSv1 ALERT:  fatal, handshake_failure
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
166  [main] DEBUG org.apache.http.impl.conn.DefaultClientConnection  - Connection org.apache.http.impl.conn.DefaultClientConnection@6b18e1c6 closed
166  [main] DEBUG org.apache.http.impl.conn.DefaultClientConnection  - Connection org.apache.http.impl.conn.DefaultClientConnection@6b18e1c6 shut down
main, called close()
main, called closeInternal(true)


[main] DEBUG org.apache.http.impl.conn.BasicClientConnectionManager  - Releasing connection org.apache.http.impl.conn.ManagedClientConnectionImpl@1f2dc289
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
        at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1979)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1086)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1332)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1359)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1343)
        at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:533)
        at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:401)
        at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:177)
        at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:304)
        at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:611)
        at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:446)
        at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:863)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:72)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:214)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:160)

你的应用程序是否在Tomcat下运行? - Stefano Zanini
不是的。我正在向一个服务发出GET请求。使用Java8我可以轻松完成。同时,在我的Chrome浏览器中,我也可以查看请求的输出。 - orange14
你如何获取SSL上下文?SSLContext context = SSLContext.getInstance("TLSv1.2");? - SSC
最好粘贴堆栈跟踪以便让其他人决定出错了什么,而不是你告诉他们你认为出了什么问题。 - SSC
1
我也不得不处理一个遗留应用程序,关键是要将 -Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2 传递给Java命令。如果这样做不起作用,答案可能在于Apache HTTP而不是运行时。 - Gimby
5个回答

2

我遇到了同样的问题,由于我是使用Apache HTTP Client库进行请求,我通过以下方式初始化我的HttpClient来解决它:

CloseableHttpClient client = HttpClients.custom()
                                 .setSSLSocketFactory(getSSLContext())
                                 .build();

getSSLContext() 方法的位置在这里。

private SSLConnectionSocketFactory getSSLContext() throws NoSuchAlgorithmException {
    return new SSLConnectionSocketFactory(
          SSLContext.getDefault(),
          new String[]{"TLSv1.2"},
          null,
          new NoopHostnameVerifier());
}

很不幸,我正在使用org.apache.http.client.methods.HttpUriRequest。这是从一个超类中导入的,而我不想修改它,因为许多类都继承自它。这段代码是5年前由别人编写的。 - orange14

1

如果有人遇到类似问题,我会回答自己的问题:

我花了两天时间尝试各种方法,最终找到了解决方法。

Java-7-oracle中不可能使用TLS1.2。即使在系统属性或SSLContext级别进行配置也无法帮助我。他们的支持非常糟糕。虽然在Java-8-oracle中是可能的。

对我来说,简单地将我的Java更改为java-7-openjdk-amd64就解决了问题。


该死,我正在使用OpenJDK,所以我必须进一步研究这个问题。我本来希望告诉我的团队“我们做不到!” - Sridhar Sarnobat

0

我曾经遇到过类似的问题,在WebLogic 10.3中无法启用Java JDK 1.7.0_80中的TLSv1.2,我们将其升级到JDK 1.7.0_181后,问题得到了解决。


0
您可以升级您的Java 7版本至1.7.0_131-b31。
针对Oracle网站上的JRE 1.7.0_131-b31:
TLSv1.2和TLSv1.1现在已默认在TLS客户端端点上启用。这类似于JDK 8版本中已经发生的行为。

0

我也有类似的问题,需要多天时间来解决所有的难题。由于我的 Java 运行在 HSM 上,无法更新 JRE 版本。也许有其他人有这样的需求。

给定:

  • JRE 1.7.0_25
  • TOMCAT 8.0.9

要求:Tomcat 上运行的 Web 应用程序应该能够连接到一个 TLSv1.2 的套接字。

问题 1:

JRE 1.7.0_25 本身无法连接到 TLSv1.2 套接字。

解决方案:

使用 BouncyCastle 库来解决:https://www.bouncycastle.org

问题 2(需要多天时间来解决):

BouncyCastle 已经被激活并添加到安全提供程序的第一位,但在创建 SSLContext 和其他实例(证书、密钥存储、TrustManager)时仍未被使用。

解决方案:

通过以下代码强制在JSSE中使用BouncyCastle作为安全提供程序:

BouncyCastleProvider provider = new BouncyCastleProvider();
Security.insertProviderAt(new BouncyCastleJsseProvider(provider), 1);
Security.insertProviderAt(provider, 2);

用这个代替:

Security.insertProviderAt(new BouncyCastleProvider(), 2);
Security.insertProviderAt(new BouncyCastleJsseProvider(), 1);

但这导致了下一个问题:

问题3:

java.lang.SecurityException:JCE无法验证提供程序BC

解决方案:

BouncyCastle的最新jar包(bcprov-jdk15on-162.jar)以及之前的版本(bcprov-jdk15on-161.jar)未经适当签名,因此不能与1.7.0_25兼容。但是,版本160的bcprov-jdk15on-160.jar是可以的。 在使用版本160之后,我终于能够使用以下代码通过TLSv1.2连接到套接字:

private static SSLContext createSSLContextBouncy(String base64Cert) {

  BouncyCastleProvider provider = new BouncyCastleProvider();
  Security.insertProviderAt(new BouncyCastleJsseProvider(provider), 1);
  Security.insertProviderAt(provider, 2);

  LOGGER.debug("Using bouncy castle as security provider");

  try {
    byte[] certBytes = Base64.decodeBase64(base64Cert);
    X509Certificate cert =
      (X509Certificate) CertificateFactory.getInstance("X.509", "BC").generateCertificate(new ByteArrayInputStream(certBytes));

    KeyStore keystore = KeyStore.getInstance("BKS", "BC");
    keystore.load(null);
    keystore.setCertificateEntry("alias", cert);

    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX", "BCJSSE");
    trustManagerFactory.init(keystore);
    TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();

    SSLContext sslContext = SSLContext.getInstance("TLS", "BCJSSE");
    sslContext.init(null, trustManagers, new SecureRandom());
    return sslContext;
  } catch (Exception e) {
    throw new RuntimeException(e);
  }
}

遗憾的是,在Tomcat内部它仍然无法工作。

问题4:

当我将代码作为Web应用程序(在Tomcat上)运行时,与TLSv1.2的连接仍然无法工作。握手开始了,但以"连接被拒绝"的错误结束。

解决方案:

在HSM上运行的Tomcat版本(也许还有其他版本)由于某种原因需要30秒来完成握手,但端点设有10秒的超时时间。我测试了另一个版本的Tomcat(8.0.37,因为我们有可能支持HSM),它运行得很顺利。

希望这能对大家有所帮助。


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