配置“DataSource”以使用 SSL/TLS 加密连接到 Digital Ocean 上的托管 Postgres 服务器

2024-05-17

我正在尝试托管数据库服务 https://www.digitalocean.com/products/managed-databases/ on 数字海洋网 https://en.wikipedia.org/wiki/DigitalOcean,创建了一个 Postgres 实例 https://www.digitalocean.com/products/managed-databases-postgresql/.

Digital Ocean 默认要求进行远程连接SSL https://en.wikipedia.org/wiki/Transport_Layer_Security(实际上TLS https://en.wikipedia.org/wiki/Transport_Layer_Security)加密。

如何配置一个JDBC https://en.wikipedia.org/wiki/Java_Database_Connectivity DataSource https://docs.oracle.com/en/java/javase/11/docs/api/java.sql/javax/sql/DataSource.html提供与此类数据库服务器的连接的实现?

这个问题类似于产生一个DataSourcePostgres JDBC 对象,以编程方式 https://stackoverflow.com/q/45091981/642706但添加了 SSL/TLS 加密和远程使用托管数据库的特定元素。


获得一个DataSource执行

通常你的JDBC驱动程序 https://en.wikipedia.org/wiki/JDBC_driver提供了一个实现javax.sql.DataSource https://docs.oracle.com/en/java/javase/11/docs/api/java.sql/javax/sql/DataSource.html.

有关更多详细信息,请参阅我的答案 https://stackoverflow.com/a/45091982/642706类似的问题。

PGSimpleDataSource

如果使用 JDBC 驱动程序jdbc.postgresql.org https://jdbc.postgresql.org,您可以使用org.postgresql.ds.PGSimpleDataSource https://jdbc.postgresql.org/documentation/publicapi/org/postgresql/ds/PGSimpleDataSource.html类作为你的DataSource执行。

实例化类型的对象PGSimpleDataSource,然后调用 setter 方法来提供连接到数据库服务器所需的所有信息。 DigitalOcean 站点上的网页列出了您的特定数据库实例的所有这些信息。

基本上是这样的:

PGSimpleDataSource dataSource = new PGSimpleDataSource();

dataSource.setServerName( "your-server-address-goes-here" );
dataSource.setPortNumber( your-port-number-goes-here );
dataSource.setDatabaseName( "defaultdb" );
dataSource.setUser( "doadmin" );
dataSource.setPassword( "your-password-goes-here" );

复数服务器名称和端口号

不幸的是,这些方法的单一版本setServerName and setPortNumber已弃用。虽然很烦人,但我们应该使用这些方法的复数版本(setServerNames & setPortNumbers)每个都采用一个数组。我们填充一对单元素数组,String[] and int[],以及我们服务器的地址和端口号 https://en.wikipedia.org/wiki/Port_(computer_networking)使用数组文字:

  • {“您的服务器地址位于此处”}
  • { 这里是您的端口号 }
PGSimpleDataSource dataSource = new PGSimpleDataSource();

String[] serverAddresses = { "your-server-address-goes-here" };
dataSource.setServerNames( serverAddresses );
int[] serverPortNumbers = { your-port-number-goes-here };
dataSource.setPortNumbers( serverPortNumbers );
dataSource.setDatabaseName( "defaultdb" );
dataSource.setUser( "doadmin" );
dataSource.setPassword( "your-password-goes-here" );

SSL/TLS 加密

最后,我们需要添加问题中解决的 SSL/TLS 加密的信息。

讽刺的是,做not call setSsl( true )

你可能会认为我们会调用setSsl https://jdbc.postgresql.org/documentation/publicapi/org/postgresql/ds/common/BaseDataSource.html#setSsl-boolean-方法和通过true。但不是。虽然违反直觉,但将其设置为 true 将导致您的连接尝试失败。我不知道这是为什么。但反复试验让我避免了这个决定。

CA证书

为了让您的客户端 Java 应用程序初始化 SSL/TLS 连接,JDBC 驱动程序必须有权访问CA证书由数字海洋使用。在您的 Digital Ocean 管理页面上,单击Download CA certificate下载小文本文件的链接。该文件将被命名为ca-certificate.crt.

我们需要将该文件的文本作为字符串提供给我们的 JDBC 驱动程序。执行以下操作将文件加载到文本字符串中。

// Get CA certificate used in TLS connections.
Path path = Paths.get( "/Users/basilbourque/Downloads/ca-certificate.crt" );
String cert = null;
try
{
    cert = Files.readString( path , StandardCharsets.UTF_8 );
    System.out.println( "cert = " + cert );
}
catch ( IOException ex )
{
    throw new IllegalStateException( "Unable to load the TLS certificate needed to make database connections." );
}
Objects.requireNonNull( cert );
if ( cert.isEmpty() ) {throw new IllegalStateException( "Failed to load TLS cert." ); }

通过调用将该 CA 证书文本传递给您的 JDBC 驱动程序DataSource::setSslCert https://jdbc.postgresql.org/documentation/publicapi/org/postgresql/ds/common/BaseDataSource.html#setSslCert-java.lang.String-。请注意,我们是not呼叫setSslRootCert https://jdbc.postgresql.org/documentation/publicapi/org/postgresql/ds/common/BaseDataSource.html#setSslRootCert-java.lang.String-。不要混淆这两个名称相似的方法。

dataSource.setSslCert( cert );

测试连接

最后我们就可以使用配置好的DataSource对象来建立与数据库的连接。该代码将如下所示:

// Test connection
try (
        Connection conn = dataSource.getConnection() ;
        // …
)
{
    System.out.println( "DEBUG - Postgres connection made. " + Instant.now() );
    // …
}
catch ( SQLException e )
{
    e.printStackTrace();
}

完整的示例代码

把所有这些放在一起,看到这样的东西。

// Get CA certificate used in TLS connections.
Path path = Paths.get( "/Users/basilbourque/Downloads/ca-certificate.crt" );
String cert = null;
try
{
    cert = Files.readString( path , StandardCharsets.UTF_8 );
    System.out.println( "cert = " + cert );
}
catch ( IOException ex )
{
    throw new IllegalStateException( "Unable to load the TLS certificate needed to make database connections." );
}
Objects.requireNonNull( cert );
if ( cert.isEmpty() ) {throw new IllegalStateException( "Failed to load TLS cert." ); }

// PGSimpleDataSource configuration
PGSimpleDataSource dataSource = new PGSimpleDataSource();

String[] serverAddresses = { "your-server-address-goes-here" };
dataSource.setServerNames( serverAddresses );
int[] serverPortNumbers = { your-port-number-goes-here };
dataSource.setPortNumbers( serverPortNumbers );
dataSource.setSslCert( cert );
dataSource.setDatabaseName( "defaultdb" );
dataSource.setUser( "doadmin" );
dataSource.setPassword( "your-password-goes-here" );

// Test connection
try (
Connection conn = dataSource.getConnection() ;
// …
)
{
System.out.println( "DEBUG - Postgres connection made. " + Instant.now() );
// …
}
catch ( SQLException e )
{
e.printStackTrace();
}

可信来源

在 DigitalOcean.com 上创建 Postgres 实例时,您将能够限制传入的连接请求。您可以指定 Postgres 服务器所需的单个 IP 地址,这是 Digital Ocean 行话中的“可信源”。任何尝试连接到您的 Postgres 服务器的黑客都将被忽略,因为它们来自其他 IP 地址。

提示:在该 IP 地址号码的数据输入字段内单击,让网页自动检测并提供您的网络浏览器当前使用的 IP 地址。如果您从同一台计算机运行 Java 代码,请使用相同的 IP 号码作为您的单一可信源。

否则,请输入运行 Java JDBC 代码的计算机的 IP 地址。

其他事宜

我还没有详细阐述,例如用于管理 CA 证书文件的适当安全协议,或者通过获取DataSource对象从一个JNDI https://en.wikipedia.org/wiki/Java_Naming_and_Directory_Interface服务器而不是硬编码 https://en.wikipedia.org/wiki/Hard_coding。但希望上面的示例可以帮助您入门。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

配置“DataSource”以使用 SSL/TLS 加密连接到 Digital Ocean 上的托管 Postgres 服务器 的相关文章

随机推荐