繁体   English   中英

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

[英]Configure a `DataSource` to connect to a managed Postgres server on Digital Ocean with SSL/TLS encryption

我正在DigitalOcean.com上尝试托管数据库服务,并创建了一个 Postgres 实例

Digital Ocean 默认要求使用SSL (实际上是TLS )加密进行远程连接。

如何配置JDBC DataSource实现以提供与此类数据库服务器的连接?

此问题类似于Produce a DataSource object for Postgres JDBC,以编程方式添加 SSL/TLS 加密的特定元素并远程使用托管数据库。

获取DataSource实现

通常您的JDBC 驱动程序提供javax.sql.DataSource的实现。

有关更多详细信息,请参阅我对类似问题的回答

PGSimpleDataSource

If using the JDBC driver from jdbc.postgresql.org , you can use the org.postgresql.ds.PGSimpleDataSource class as your DataSource implementation.

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

基本上是这样的:

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" );

复数服务器名称和端口号

不幸的是, setServerNamesetPortNumber方法的单一版本已被弃用。 虽然烦人,但我们可能应该使用这些方法的复数版本( setServerNamessetPortNumbers ),它们每个都采用一个数组。 我们使用数组文字填充一对单元素 arrays、 String[]int[] ,以及我们的服务器地址和端口号

  • {“你的服务器地址去这里”}
  • {你的端口号去这里}
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 加密添加信息。

具有讽刺意味的是,不要调用setSsl( true )

你会认为我们会调用setSsl方法并传递true 但不是。 虽然违反直觉,但将其设置为 true 会导致您的连接尝试失败。 我不知道为什么会这样。 但是反复试验使我避免了那个电话。

CA 证书

为了让您的客户端 Java 应用程序启动 SSL/TLS 连接,JDBC 驱动程序必须有权访问 Digital Ocean 使用的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." ); }

通过调用DataSource::setSslCert将该 CA 证书文本传递给您的 JDBC 驱动程序。 请注意,我们没有调用setSslRootCert 不要混淆这两种名称相似的方法。

dataSource.setSslCert( cert );

测试连接

最后,我们可以使用配置的DataSource object 来连接数据库。 该代码将如下所示:

// 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 地址。

Tip: Click inside the data-entry field for this IP address number to have the web page automatically detect and offer the IP address being currently used by your web browser. 如果您在同一台计算机上运行 Java 代码,请使用相同的 IP 编号作为您的单一可信来源。

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

其他问题

我没有详细说明,例如用于管理您的 CA 证书文件的适当安全协议,或者例如通过从JNDI服务器获取DataSource object 而不是硬编码来外部化您的连接信息。 但希望上面的示例可以帮助您入门。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM