Overview
在本指南中,您可以了解如何使用TLS 协议保护与 MongoDB 部署的连接。 TLS 是一种加密协议,可保护应用程序与 MongoDB 之间的通信。 要将连接配置为使用 TLS,请启用 TLS 选项并在创建客户端时提供证书以进行验证。
默认情况下,驱动程序使用 JDK 提供的 TLS/SSL 根本支持来支持与 MongoDB 服务器的 TLS/SSL 连接。这可以通过使用Netty API或Java SE API的可扩展性来更改。
提示
异步应用程序首选 Netty
对于异步应用程序,我们建议使用 Netty,因为它支持异步 I/O 并有效处理高连接量。要学习;了解如何使用 Netty 配置 TLS 设置,请参阅本指南的使用 Netty SslContext 配置 TLS/SSL部分。
MongoClient API
您可以通过在 ConnectionString 或 MongoClientSettings实例中指定选项,将驱动程序配置为使用 TLS/SSL。
在 ConnectionString 中指定 TLS/SSL
包括以下 import 语句:
import com.mongodb.reactivestreams.client.MongoClients; import com.mongodb.reactivestreams.client.MongoClient;
要在 ConnectionString 中指定 TLS/SSL,请将 ssl=true 指定为连接string的一部分:
MongoClient mongoClient = MongoClients.create("mongodb://localhost/?ssl=true");
在 MongoClientSettings 中指定 TLS/SSL
包括以下 import 语句:
import com.mongodb.MongoClientSettings; import com.mongodb.reactivestreams.client.MongoClients; import com.mongodb.reactivestreams.client.MongoClient;
要在MongoClientSettings实例中指定 TLS/SSL,请将enabled属性设置为true :
MongoClientSettings settings = MongoClientSettings.builder() .applyToSslSettings(builder -> builder.enabled(true)) .build(); MongoClient client = MongoClients.create(settings);
使用 Netty SslContext 配置 TLS/SSL
包括以下 import 语句:
import com.mongodb.MongoClientSettings; import com.mongodb.client.MongoClients; import com.mongodb.client.MongoClient; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.SslProvider;
注意
Netty 包版本
驱动程序使用 Netty包版本进行测试 io.netty:netty-all:4.1.87.Final
要指示驱动程序使用 io.netty.handler.ssl.SslContext,请在定义 MongoClientSettings 时配置 NettyTransportSettings。
使用MongoClientSettings.Builder.transportSettings()和NettyTransportSettings.Builder.sslContext()构建设置:
SslContext sslContext = SslContextBuilder.forClient() .sslProvider(SslProvider.OPENSSL) .build(); MongoClientSettings settings = MongoClientSettings.builder() .applyToSslSettings(builder -> builder.enabled(true)) .transportSettings(TransportSettings.nettyBuilder() .sslContext(sslContext) .build()) .build(); MongoClient client = MongoClients.create(settings);
有关 io.netty.handler.ssl.SslProvider 的更多详细信息,请参阅Netty 文档。
在 MongoClientSettings 中指定 Java SE SSLContext
包括以下 import 语句:
import javax.net.ssl.SSLContext; import com.mongodb.MongoClientSettings; import com.mongodb.MongoClient;
要将javax.net.ssl.SSLContext指定为MongoClientSettings ,请设置sslContext属性:
SSLContext sslContext = ... MongoClientSettings settings = MongoClientSettings.builder() .applyToSslSettings(builder -> builder.enabled(true).context(sslContext)) .build(); MongoClient client = new MongoClient(settings);
禁用主机名验证
默认情况下,驱动程序确保服务器的 SSL 证书中包含的主机名与构造MongoClient时提供的主机名匹配。
如果您的应用程序需要禁用主机名验证,则必须在MongoClientSettings中明确指示:
MongoClientSettings settings = MongoClientSettings.builder() .applyToSslSettings(builder -> { builder.enabled(true); builder.invalidHostNameAllowed(true); }) .build();
常见 TLS/SSL 配置任务
本节基于Oracle JDK 的文档,因此某些部分可能不适用于您的 JDK 或您使用的自定义 TLS/SSL实施。
配置信任存储和密钥存储
您可以使用javax.net.ssl.SSLContext.init(KeyManager[] km, TrustManager[] tm, SecureRandom random)配置特定于客户端的信任存储和密钥存储,也可以设置 JVM 默认值。
设置默认信任存储
典型的应用程序需要设置多个 JVM 系统属性,以确保客户端可以验证服务器提供的 TLS/SSL 证书:
javax.net.ssl.trustStore:包含签名机构证书的信任存储区的路径javax.net.ssl.trustStorePassword:用于访问此信任存储区的密码
信任存储区通常使用作为 JDK 的一部分提供的keytool命令行程序创建:
keytool -importcert -trustcacerts -file <path to certificate authority file> -keystore <path to trust store> -storepass <trust store password>
设置默认密钥存储
典型的应用程序还需要设置多个 JVM 系统属性,以确保客户端向 MongoDB 服务器提供TLS/SSL 客户端证书:
javax.net.ssl.keyStore:包含客户端 TLS/SSL 证书的密钥存储区的路径javax.net.ssl.keyStorePassword:访问此密钥存储区的密码
密钥存储通常使用 keytool 或 openssl 命令行程序创建。示例,如果您有一个包含客户端证书及其私钥的文件,并且您想创建 PKCS #12 格式的密钥存储,则可以运行以下命令:
openssl pkcs12 -export -in <path to client certificate & private key file> -out <path to key store> -passout pass:<trust store password>
要学习;了解有关为 TLS/SSL 配置Java应用程序的更多信息,请参阅JSSE 参考指南。
强制 TLS v 1.2
某些应用程序可能只想强制使用 TLS 1.2协议。 为此,请将jdk.tls.client.protocols系统属性设置为TLSv1.2 。
Java 8开始之前的 Java 运行时环境仅在以后的更新中启用 TLS 1.2协议,如上一节所示。 为了使驱动程序在 Java 8之前强制 Java 运行时环境使用 TLS 1.2协议,请确保更新已启用 TLS 1.2 。
OCSP
注意
驱动程序无法在单个MongoClient的基础上默认启用 OCSP。
注意
Let's Encrypt OCSP 已弃用
Let's Encrypt 已经结束对较新证书的 OCSP 支持。Let's Encrypt 颁发的新证书可能不包含 OCSP 响应端 URL。OCSP 撤销检查仅在证书包含 OCSP URI 时发生,因此,缺失 OCSP URL 是预期的,并不一定表明 MongoDB 部署存在问题。
客户端驱动的 OCSP
应用程序需要设置以下 JVM 系统和安全属性,以确保启用客户端驱动的 OCSP:
com.sun.net.ssl.checkRevocation:设置为true时,此系统属性启用撤销检查ocsp.enable:当设置为true时,此安全属性启用客户端驱动的 OCSP
要将应用程序配置为使用客户端驱动的 OCSP,必须已将应用程序设置为使用 TLS 连接到服务器。 要启用客户端驱动的 OCSP,需要设置这些系统属性。
注意
在 OCSP 响应程序不可用的情况下,JDK 提供的 TLS 支持会利用“硬故障”行为,而mongosh和驱动程序会利用“软故障”行为。
OCSP 装订 (Stapling)
重要
在使用 TLS 1.3协议(Java 11和更高版本默认使用 TLS 1.3 )的 Java 运行时环境中使用 OCSP 装订时,可能会出现以下异常:
javax.net.ssl.SSLHandshakeException: extension (5) should not be presented in certificate_request
该异常是由于 Java 11及更高版本中的 TLS 1.3的一个已知问题造成的。 为了在使用按 TLS 1.3协议运行的 Java 运行时环境时避免出现此异常,您可以强制应用程序使用 TLS 1.2协议。 为此,请将jdk.tls.client.protocols系统属性设置为TLSv1.2 。
应用程序需要设置多个 JVM 系统属性来设置 OCSP 装订:
jdk.tls.client.enableStatusRequestExtension:设置为true(默认值)时,将启用 OCSP 装订。com.sun.net.ssl.checkRevocation:设置为true时,将启用撤销检查。 如果此属性未设置为true,则无论吊销信息是否存在或状态如何,都允许继续连接。
要将应用程序配置为使用 OCSP 装订,必须已将应用程序设置为使用 TLS 连接到服务器,并且必须将服务器设置为将 OCSP 响应装订到它作为 TLS 握手的一部分返回的证书。
要学习;了解有关配置Java应用程序以使用 OCSP 的更多信息,请参阅Java文档中的客户端驱动的 OCSP 和 OCSPOCSP装订。