如何在Java 7中启用TLS 1.2

60

我正在尝试在使用JBoss 6.4和Java 1.7的Web应用程序中启用TLS 1.2。 我在应用程序环境中具有-Dhttp.protocols=TLSv1.2,但似乎对我不起作用。

是否有任何事情可以做以启用TLS 1.2?

我编写了一个简单的程序

context = SSLContext.getInstance("TLSv1.2");
context.init(null,null,null);
SSLContext.setDefault(context); 
SSLSocketFactory factory = (SSLSocketFactory)context.getSocketFactory();
SSLSocket socket = (SSLSocket)factory.createSocket();
protocols = socket.getEnabledProtocols();
在应用程序中运行此程序后,TLS 1.2将被启用。我不想运行此程序,但我想在应用程序启动时直接启用它。有没有办法做到这一点?

在应用程序启动时直接启用TLS 1.2,而不是运行该程序。有没有办法实现?


1
sysprop https.protocols 只有在两个 s 都拼写正确的情况下才能工作,并且仅适用于使用 URL.openConnection 进行连接而不是其他方式(如 SSLSocketFactory)。 - dave_thompson_085
11个回答

48

有许多建议,但我发现其中两个最常见。

JAVA_OPTS相关

我首先尝试在程序启动之前在命令行上使用export JAVA_OPTS="-Dhttps.protocols=SSLv3,TLSv1,TLSv1.1,TLSv1.2",但对我没有用。

构造函数相关

然后我在启动类的构造函数中添加了以下代码,这对我有效。

try {
        SSLContext ctx = SSLContext.getInstance("TLSv1.2");
        ctx.init(null, null, null);
        SSLContext.setDefault(ctx);
} catch (Exception e) {
        System.out.println(e.getMessage());
}

坦白地说,我不太清楚为什么ctx.init(null, null, null);可以正常工作,但所有(SSL/TLS)都对我有效。

关于 System.setProperty

还有一种选项:System.setProperty("https.protocols", "SSLv3,TLSv1,TLSv1.1,TLSv1.2");。这也需要在代码中使用,但我没有尝试过。


2
这应该是被接受的答案。在Java 7_80中,-Dhttps.protocols="TLSv1.2"属性作为Java opts似乎存在一个错误。 - karnesJ.R
1
我也尝试了Java选项(例如https.protocols),但没有起作用 - 似乎它甚至没有查看该选项。 - Victor
我已经尝试在网上搜索,有没有关于@karnesJ.R的这个问题是一个bug的证据?我正在使用Java 7_51,我也遇到了同样的问题,这个解决方案对我也起作用。 - JordC1995
我已经尝试在网上搜索了,有没有关于这个问题是个bug的证据,@karnesJ.R?我正在使用Java 7_51,我也遇到了同样的问题,这个解决方案对我也起作用。 - undefined
对我来说,在Java版本1.7.0_80中,System.setProperty("https.protocols", "SSLv3,TLSv1,TLSv1.1,TLSv1.2");是有效的! - Harish Kumar

26

您可以将Java 7版本升级到1.7.0_131-b31

在Oracle网站上,针对JRE 1.7.0_131-b31:

TLSv1.2和TLSv1.1现在已在TLS客户端端点上默认启用。这类似于JDK 8版本的行为。


你能分享这个链接给我吗? - Uday Reddy
1
https://www.oracle.com/technetwork/java/javase/7u131-relnotes-3338543.html - Joby Wilson Mathews
1
这是一个发布说明页面。我该如何下载jdk? - Uday Reddy
1
@UdayReddy,您需要成为业务用户才能下载。 - Joby Wilson Mathews
4
非商业版本jdk1.7.0_80对我有效,但是我确实需要按照Ankit和Meeraj的建议添加-Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2 - JGlass
我确认它可以在jdk1.7.0_80上工作,只需记得使用此jdk编译类。 - luandrea

16

为 Java 应用程序添加以下选项:

-Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2  

2
我有一个问题,这个更改是什么作用?它是否为所有传入和传出的连接请求启用TLS? 是否有一种方法记录TLS握手过程? - praxmon

9
将以下参数添加到JAVA_OPTS或Maven命令行中:-Dhttps.protocols=TLSv1.2

7

System.setProperty("https.protocols", "TLSv1.2");在我的案例中起作用了。你是否已经在应用程序中进行了检查?


这是一个COTS产品。我不能使用它。至少当系统启动时,我不知道如何使用它。 - New Bee
你是否在这种情况下检查了 https://developer.jboss.org/thread/251967?start=0&tstart=0? - Sirsendu

6
所列出的答案是正确的,但我想分享一个在我的情况下适用的额外注意事项:除了使用setProtocol/withProtocol之外,您可能会遇到一些恶心的jar文件,即使您拥有正确的jar文件和旧版本也无法消除它们:

删除

<dependency>
    <groupId>commons-httpclient</groupId>
    <artifactId>commons-httpclient</artifactId>
    <version>3.1</version>
</dependency>

保留

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.2</version>
</dependency>

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpcore</artifactId>
    <version>4.4.6</version>
</dependency>

Java是向后兼容的,但大多数库不是。随着时间的推移,我越来越希望禁止共享库,因为这样缺乏责任感。

更多信息

java version "1.7.0_80"
Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)

Sridhar,所以通过这些更改以及Dhttp.protocols = TLSv1.2,1.7.0_80默认支持TLSv1.2吗(因为我看到sslHandshake正在使用TLSv1),还是我需要升级我们的JDK到较新版本?即使我在eclipse运行时环境中提供了“-Dhttps.protocols = TLSv1.2”或在catalina属性中提供了“https.protocols = TLSv1.2”,它也不起作用!! - whoami - fakeFaceTrueSoul
我感同身受。我理解在某些情况下升级是不可能的。它在Java 7上对我有用,但我需要我的架构师找出这个不必要的jar文件。 - Sridhar Sarnobat
是的,谢谢建议,但不知何故对我无效,每次都会将其默认为TLSv1。 - whoami - fakeFaceTrueSoul

2

在创建JDBC连接之前,我需要使用以下代码片段来强制启用JRE7u_80中的TLSv1.2。

import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import javax.net.ssl.SSLContextSpi;
import sun.security.jca.GetInstance;
import sun.security.jca.ProviderList;
import sun.security.jca.Providers;

public static void enableTLSv12ForMssqlJdbc() throws NoSuchAlgorithmException
{
    ProviderList providerList = Providers.getProviderList();
    GetInstance.Instance instance = GetInstance.getInstance("SSLContext", SSLContextSpi.class, "TLS");
    for (Provider provider : providerList.providers())
    {
        if (provider == instance.provider)
        {
            provider.put("Alg.Alias.SSLContext.TLS", "TLSv1.2");
        }
    }
}

能够连接启用TLSv1.2操作系统的Windows 10,并与SQL Server 2017建立连接。

0

在连接到RDS Oracle时,即使客户端和服务器都设置为TLSv1.2且证书正确,并且Java版本为1.8.0_141,我仍然遇到了类似的问题。 最后,我不得不在Java加密扩展(JCE)无限制权限策略文件上应用补丁。

应用补丁后,问题消失了,连接正常进行。


0

你可能应该查找通过 -Djdk.tls.client.protocols=TLSv1.2 控制底层平台 TLS 实现的配置。


6
似乎只支持JDK 1.7.0_95或更高版本,但问题在于JDK 1.7的最后一个公共发行版/更新是JDK 1.7.0_80,因此从技术上讲,这对于使用具有Oracle支持或是Oracle客户端的JDK版本的人有效!请告诉我它是否适用于JDK 1.7.0_80。 - whoami - fakeFaceTrueSoul
这适用于Azul Zulu OpenJDK 7。 - David T

0

Service.setSslSecurityProtocol(SSLSecurityProtocol.TLSv1_2);

你能否也写一下我们在Android Studio中应该添加这段代码的位置。并不是每个人都像你一样专业,所以请考虑那些刚入门编程或想要实现这个简单解决方案的人们...!


1
不是一种恰当的沟通方式。 - Harsh

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