在连接上启用 TLS/SSL
在此页面上
Overview
通过本指南,您可以了解如何利用 JDK 中的底层 TLS/SSL 支持,通过 TLS/SSL 安全协议连接到 MongoDB 实例。要配置连接以使用 TLS/SSL,请在 ConnectionString 或 MongoClientSettings 中启用 TLS/SSL 设置。
注意
调试 TLS/SSL
如果在建立 TLS/SSL 连接时遇到问题,您可以使用 -Djavax.net.debug=all
系统属性查看更多日志语句。有关更多信息,请参阅 Oracle TLS/SSL 连接调试指南。
启用 TLS/SSL
您可以通过两种不同的方式为 MongoDB 实例的连接启用 TLS/SSL:通过连接字符串中的参数,或使用 MongoClientSettings.Builder
类中的方法。
注意
如果您使用 DNS 种子列表协议(由连接字符串中的 mongodb+srv
前缀表示)进行连接,则驱动程序会启用 TLS/SSL。要禁用 TLS/SSL,请在连接字符串或 MongoClientSettings
实例中将 tls
或 ssl
参数值设为 false
。
要进一步了解使用 DNS 种子列表时的连接行为,请参阅服务器手册中的 SRV 连接格式部分。
在使用 ConnectionString 的连接上启用TLS/SSL ,在传递给string tls
true
的连接 中为连接 参数 分配值string MongoClients.create()
:
MongoClient mongoClient = MongoClients.create("mongodb+srv://<db_username>:<db_password>@<cluster-url>?tls=true");
要使用 MongoClientSettings.Builder
类来配置 MongoClient
的 TLS/SSL 连接选项,请调用 applyToSslSettings() 方法。在 SslSettings.Builder
区块中将 enabled
属性设置为 true
以启用 TLS/SSL:
MongoClientSettings settings = MongoClientSettings.builder() .applyToSslSettings(builder -> builder.enabled(true)) .build(); MongoClient client = MongoClients.create(settings);
配置证书
启动 TLS/SSL 请求的 Java 应用程序需要访问加密证书,这些证书证明应用程序本身以及与应用程序交互的其他应用程序的身份。您可以通过以下机制,在应用程序中配置这些证书的访问权限:
JVM 信任存储区与 JVM 密钥存储区
特定于客户端的信任存储和密钥存储
注意
以下部分基于 Oracle JDK 的文档,因此某些部分可能不适用于您的 JDK 或所使用的自定义 TLS/SSL 实施。
配置 JVM 信任存储区
注意
默认情况下,JRE 包含许多来自 Let's Encrypt 等签名机构的常用公共证书。因此,您可以使用 TLS/SSL 连接到 MongoDB Atlas 实例(或由 JRE 默认证书存储区中的授权机构签署证书的任何其他服务器),而无需配置信任存储区。
JVM 信任存储所保存的证书可以安全地识别与您的 Java 应用程序交互的其他应用程序。使用这些证书,您的应用程序可以证明与另一应用程序的连接是真实、安全的,不会被第三方篡改。
如果 MongoDB 实例使用的证书由没有位于 JRE 默认证书存储中的颁发机构进行签名,您的应用程序必须配置两个系统属性以启动 SSL/TLS 请求。这些属性确保应用程序可以验证连接的 MongoDB 实例提供的 TLS/SSL 证书。
javax.net.ssl.trustStore
:包含签名机构证书的信任存储区的路径javax.net.ssl.trustStorePassword
:用于访问以下项中定义的信任库的密码:javax.net.ssl.trustStore
您可以使用 JDK 中提供的 keytool 命令行工具来创建信任库:
keytool -importcert -trustcacerts -file <path to certificate authority file> -keystore <path to trust store> -storepass <password>
配置 JVM 密钥存储库
注意
默认情况下,MongoDB 实例不执行客户端证书验证。如果将 MongoDB 实例配置为验证客户端证书,您必须配置密钥存储。
JVM 密钥存储区可保存证书,用于向其他应用程序安全地标识 Java 应用程序。使用这些证书,其他应用程序可以证明与您的应用程序的连接是真实的,并且是安全的,不会被第三方篡改。
发起 TLS/SSL 请求的应用程序需要设置两个 JVM 系统属性,以确保客户端向 MongoDB 部署提供 TLS/SSL 证书:
javax.net.ssl.keyStore
:包含客户端 TLS/SSL 证书的密钥存储区的路径javax.net.ssl.keyStorePassword
:用于访问以下项中定义的密钥库的密码:javax.net.ssl.keyStore
您可以使用 keytool 或 openssl 命令行工具创建密钥存储。
有关配置 Java 应用程序以使用 TLS/SSL 的更多信息,请参阅 JSSE 参考指南。
配置特定于客户端的信任存储和密钥存储
您可以使用 SSLContext
类的 init()
方法配置客户端对应的信任存储区和密钥存储区。
您可以在本指南的使用 SSLContext 进行自定义 TLS/SSL 配置部分找到展示如何使用 SSLContext
实例配置客户端的示例。
有关SSLContext
类的更多信息,请参阅 SSL 上下文的 API 文档。
禁用主机名验证
默认情况下,驱动程序确保服务器的 TLS/SSL 证书中包含的主机名与构建 MongoClient
时提供的主机名匹配。要为应用程序禁用主机名验证,您可以在 applytoSslSettings()
构建器 Lambda 中将构建器的 invalidHostNameAllowed
属性设置为 true
以明确禁用该功能:
MongoClientSettings settings = MongoClientSettings.builder() .applyToSslSettings(builder -> { builder.enabled(true); builder.invalidHostNameAllowed(true); }) .build();
警告
禁用主机名验证可能会使您的配置变得不安全。请仅出于测试目的或没有其他替代方法时禁用主机名验证。
将连接限制为仅使用 TLS 1.2
要将应用程序限制为仅使用 TLS 1.2 协议,请将 jdk.tls.client.protocols
系统属性设置为“TLSv1.2”。
注意
Java 8 之前的 Java 运行时环境 (JRE) 仅在更新版本中启用了 TLS 1.2 协议。如果您的 JRE 未启用 TLS 1.2 协议,请升级到更高版本以使用 TLS 1.2 进行连接。
通过 Java SE SSLContext 自定义 TLS/SSL 配置
如果您的 TLS/SSL 配置需要进行自定义,您可以在 applyToSslSettings()
Lambda 中将一个 SSLContext 对象传递给生成器以设置 MongoClient
的 sslContext
属性:
SSLContext sslContext = ... MongoClientSettings settings = MongoClientSettings.builder() .applyToSslSettings(builder -> { builder.enabled(true); builder.context(sslContext); }) .build(); MongoClient client = MongoClients.create(settings);
通过 Netty SslContext 自定义 TLS/SSL 配置
如果您将驱动程序与 Netty 配合使用以进行网络 IO,则可以选择插入 Netty 提供的替代 TLS/SSL 协议实现。
import com.mongodb.MongoClientSettings; import com.mongodb.client.MongoClients; import com.mongodb.client.MongoClient; import com.mongodb.connection.netty.NettyStreamFactoryFactory; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.SslProvider;
注意
驱动程序使用 Netty 版本进行测试 io.netty:netty-all:4.1.79.Final
要指示驱动程序使用io.netty.handler.ssl.SslContext ,请使用NettyStreamFactoryFactory.Builder.sslContext方法。 有关驱动程序支持的不同 io.netty.handler.ssl.SslProvider 变体以及使用它们带来的影响,请参阅方法文档,了解详情。
SslContext sslContext = SslContextBuilder.forClient() .sslProvider(SslProvider.OPENSSL) .build(); MongoClientSettings settings = MongoClientSettings.builder() .applyToSslSettings(builder -> builder.enabled(true)) .streamFactoryFactory(NettyStreamFactoryFactory.builder() .sslContext(sslContext) .build()) .build(); MongoClient client = MongoClients.create(settings);
在线证书状态协议 (OCSP)
OCSP 是一种用于检查是否已撤销 X.509 证书的标准。证书颁发机构 (CA) 可以在到期时间之前将 X.509 证书添加到证书撤销列表 (CRL) 中,以使该证书失效。当客户端在 TLS 握手期间发送 X.509 证书时,CA 的撤销服务器检查 CRL 并返回“良好”、“已撤销”或“未知”状态。
该驱动程序支持以下 OCSP 变体:
客户端驱动的 OCSP
OCSP 装订 (Stapling)
以下部分描述了变体之间的差异以及如何为您的应用程序启用这些变体。
注意
Java 驱动程序使用为应用程序配置的 JVM 参数,并且无法针对特定的 MongoClient
实例进行重写。
客户端驱动的 OCSP
在客户端驱动的 OCSP 中,客户端在收到服务器发送的证书后,将 OCSP 请求中的证书发送给 OCSP 响应程序。OCSP 响应程序通过证书颁发机构 (CA) 检查证书的状态,并在发送给客户端的响应中报告证书是否有效。
要为您的应用程序启用客户端驱动的 OCSP,请设置以下 JVM 系统属性:
属性 | 值 |
---|---|
com.sun.net.ssl.checkRevocation | 将此属性设置为 true 以启用撤销检查。 |
ocsp.enable | 将此属性设置为 true 以启用客户端驱动的 OCSP。 |
警告
如果 OCSP 响应程序不可用,JDK 提供的 TLS 支持会报告“硬故障”。这与 MongoDB Shell 和其他一些驱动程序的“软故障”行为不同。
OCSP 装订 (Stapling)
OCSP 装订是一种机制,在该机制中,服务器必须从证书颁发机构 (CA) 获取签名证书,并将其包含在对客户端的带时间戳的 OCSP 响应中。
要为您的应用程序启用 OCSP 装订,请设置以下 JVM 系统属性:
属性 | 说明 |
---|---|
com.sun.net.ssl.checkRevocation | 将此属性设置为 true 以启用撤销检查。 |
jdk.tls.client.enableStatusRequestExtension | Set this property to true to enable OCSP stapling.If unset or set to false , the connection can proceed regardless of the presence or status of the certificate revocation response. |
有关 OCSP 的更多信息,请查看以下资源:
Oracle JDK 8 文档关于如何为应用程序启用 OCSP