[英]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" );
不幸的是, setServerName
和setPortNumber
方法的单一版本已被弃用。 虽然烦人,但我们可能应该使用这些方法的复数版本( setServerNames
和setPortNumbers
),它们每个都采用一个数组。 我们使用数组文字填充一对单元素 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 加密添加信息。
setSsl( true )
你会认为我们会调用setSsl
方法并传递true
。 但不是。 虽然违反直觉,但将其设置为 true 会导致您的连接尝试失败。 我不知道为什么会这样。 但是反复试验使我避免了那个电话。
为了让您的客户端 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.