Redrock Postgres 文档
主页 切换暗/亮/自动模式 切换暗/亮/自动模式 切换暗/亮/自动模式 返回首页

使用 SSL

主文档 中介绍了为 SSL 配置 PostgreSQL 服务器,因此此处不再赘述。源代码中证书部分中也有说明。在尝试从 Java 访问启用 SSL 的服务器之前,请确保您可以通过 psql 访问它。如果您已建立 SSL 连接,您应该看到如下所示的输出。

$ ./bin/psql -h localhost -U postgres
psql (14.5)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

postgres=#

自定义 SSLSocketFactory

PostgreSQL为开发人员提供了一种自定义SSL连接建立方式的方法。通过允许开发人员创建自己的SSLContext实例,这可用于提供自定义证书源或其他扩展。连接 URL 参数sslfactory允许用户指定用于创建SSLSocketFactory的自定义类。通过sslfactory指定的类名必须扩展javax.net.ssl.SSLSocketFactory并且可用于驱动程序的类加载器。

此类必须具有零参数构造函数或优先采用的单个Properties参数的构造函数。有一个简单的org.postgresql.ssl.DefaultJavaSSLFactory可供使用,它使用默认的 java 的SSLFactory

有关如何实际实现此类的信息超出了本文档的范围。寻求帮助的地方是 JSSE 参考指南 和 JDBC 驱动程序提供的NonValidatingFactory源代码。

配置客户端

有许多连接参数可用于为 SSL 配置客户端。请参阅 SSL 连接参数

最简单的是ssl=true ,将其传递给驱动程序将导致驱动程序验证两个 SSL 证书并验证主机名(与verify-full相同)。

注意

这与默认为非验证 SSL 连接的 libpq 不同。

在此模式下,当建立 SSL 连接时,JDBC 驱动程序将验证服务器的身份,防止 “中间人” 攻击。它通过检查服务器证书是否由受信任的颁发机构签名来实现此目的,并且要连接到的主机与证书中的主机名相同。

如果您需要加密并希望连接在无法加密时失败,则可以设置sslmode=require,此选项可确保服务器配置为接受此主机或 IP 地址的 SSL 连接,并且服务器可识别客户端证书。换句话说,如果服务器不接受 SSL 连接或者客户端证书不可识别,连接将失败。

注意

在此模式下,我们将接受所有服务器证书。

如果设置sslmode=verify-ca,则通过检查证书链直到存储在客户端上的根证书来验证服务器。

如果设置sslmode=verify-full,将验证服务器主机名,以确保它与存储在服务器证书中的名称匹配。

如果无法验证服务器证书,则 SSL 连接将失败。在大多数安全敏感型环境推荐使用verify-full

默认的 SSL 套接字工厂是LibPQFactory。如果证书验证失败,您可以尝试设置sslcert=LibPQFactory将不会发送客户端证书。如果服务器未配置进行身份验证使用的证书,它应该连接。

客户端证书的位置、PKCS-8 客户端密钥和根证书可以分别使用sslcertsslkeysslrootcert设置进行覆盖。这些参数的默认值分别为/defaultdir/postgresql.crt/defaultdir/postgresql.pk8/defaultdir/root.crt, 其中的 defaultdir 在类 Unix 系统上为${user.home}/.postgresql/,在 Windows 上为%appdata%/postgresql/

从版本 42.2.9 开始,还支持 PKCS-12。在此存档格式中,客户端密钥和客户端证书位于一个文件,文件需要使用参数sslkey进行设置。要识别 PKCS-12 格式,文件扩展名 必须是 “.p12”(自 42.2.9 起支持)或 “.pfx”(自 42.2.16 起支持)。(在这种情况下,sslcert参数会被忽略。)

可以使用连接参数sslmode实现对 SSL 连接的更精细控制。此参数与 libpq 的sslmode参数相同,当前支持以下选择。

sslmode 窃听保护 MITM 保护
disable 我不关心安全性,也不想为加密花费开销
allow 可能 我不关心安全性,但如果服务器要求,我将花费加密开销
prefer 可能 我不关心加密,但如果服务器支持,我会花费加密的开销
require 我希望对我的数据进行加密,并且我接受开销。我相信网络将确保我始终连接到我想要的服务器。
verify-ca 取决于 CA 策略 我希望对数据进行加密,并接受开销。我想确保我连接到我信任的服务器。
verify-full 我希望对数据进行加密,并接受开销。我想确保我连接到我信任的服务器,并且它是我指定的服务器。

注意

如果您使用 Java 的默认机制(不是 LibPQFactory)来创建 SSL 连接,则需要使服务器证书可供 Java 使用,第一步是将其转换为 Java 理解的形式。

openssl x509 -in server.crt -out server.crt.der -outform der

在这里最简单的方法是将此证书导入 Java 的系统信任库。

keytool -keystore $JAVA_HOME/lib/security/cacerts -alias postgresql -import -file server.crt.der

cacerts 密钥库的默认密码是changeit。不需要将别名设置为 postgresql。您可以应用任何您想要的名称。

如果您无权访问系统证书信任库,则可以创建自己的信任库。

keytool -keystore mystore -alias postgresql -import -file server.crt.der

启动 Java 应用程序时,必须指定要使用的密钥库和密码。

java -Djavax.net.ssl.trustStore=mystore -Djavax.net.ssl.trustStorePassword=mypassword com.mycompany.MyApp

如果出现问题,可以通过添加-Djavax.net.debug=ssl到命令行来获得额外的调试信息。

在没有证书验证的情况下使用 SSL

在某些情况下,可能无法配置 Java 环境以使服务器证书可用,例如在 applet 小程序中。对于大规模部署,最好获得由公认的证书颁发机构签名的证书,但这并不总是一种选择。JDBC 驱动程序提供了一个无需执行任何验证即可建立 SSL 连接的选项,但在启用此选项之前,请了解所涉及的风险。

非验证连接是通过随驱动程序提供的自定义SSLSocketFactory类建立的。设置连接 URL 参数sslfactory=org.postgresql.ssl.NonValidatingFactory将关闭所有 SSL 验证。