配置“DataSource”以使用 SSL/TLS 加密连接到 Digital Ocean 上的托管 Postgres 服务器
Configure a `DataSource` to connect to a managed Postgres server on Digital Ocean with SSL/TLS encryption
我正在尝试 managed database service on DigitalOcean.com, having created a Postgres instance。
Digital Ocean 默认要求远程连接使用 SSL (actually TLS) 加密。
如何配置 JDBC DataSource
实现以提供与此类数据库服务器的连接?
此问题类似于 ,但添加了 SSL/TLS 加密和远程使用托管数据库的特定元素。
获得DataSource
实施
通常是您的 JDBC driver provides an implementation of javax.sql.DataSource
.
有关更多详细信息,请参阅 类似问题。
PGSimpleDataSource
如果使用来自 jdbc.postgresql.org, you can use the org.postgresql.ds.PGSimpleDataSource
class 的 JDBC 驱动程序作为您的 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
和 setPortNumber
方法的单数版本已弃用。虽然很烦人,但我们应该使用这些方法的复数形式(setServerNames
& setPortNumbers
),每个方法都接受一个数组。我们用我们的服务器地址填充一对单元素数组 String[]
和 int[]
,并使用数组文字 port number:
- { “你的服务器地址在这里” }
- { 这里是你的端口号 }
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 驱动程序必须能够访问 CA 证书 由 Digital Ocean 使用。在您的 Digital Ocean 管理页面上,单击 Download CA certificate
link 下载一个小文本文件。该文件将被命名为 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
. Note that we are not calling setSslRootCert
将该 CA 证书文本传递给您的 JDBC 驱动程序。不要混淆这两个名称相似的方法。
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 号码作为您的单一可信来源。
否则,输入计算机的 IP 地址 运行 您的 Java JDBC 代码。
其他问题
我没有详细说明,例如用于管理您的 CA 证书文件的适当安全协议,或者例如通过从 JNDI server rather than hard-coding 获取 DataSource
对象来外部化您的连接信息。但希望上面的示例可以帮助您入门。
我正在尝试 managed database service on DigitalOcean.com, having created a Postgres instance。
Digital Ocean 默认要求远程连接使用 SSL (actually TLS) 加密。
如何配置 JDBC DataSource
实现以提供与此类数据库服务器的连接?
此问题类似于
获得DataSource
实施
通常是您的 JDBC driver provides an implementation of javax.sql.DataSource
.
有关更多详细信息,请参阅
PGSimpleDataSource
如果使用来自 jdbc.postgresql.org, you can use the org.postgresql.ds.PGSimpleDataSource
class 的 JDBC 驱动程序作为您的 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
和 setPortNumber
方法的单数版本已弃用。虽然很烦人,但我们应该使用这些方法的复数形式(setServerNames
& setPortNumbers
),每个方法都接受一个数组。我们用我们的服务器地址填充一对单元素数组 String[]
和 int[]
,并使用数组文字 port number:
- { “你的服务器地址在这里” }
- { 这里是你的端口号 }
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 驱动程序必须能够访问 CA 证书 由 Digital Ocean 使用。在您的 Digital Ocean 管理页面上,单击 Download CA certificate
link 下载一个小文本文件。该文件将被命名为 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
. Note that we are not calling setSslRootCert
将该 CA 证书文本传递给您的 JDBC 驱动程序。不要混淆这两个名称相似的方法。
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 号码作为您的单一可信来源。
否则,输入计算机的 IP 地址 运行 您的 Java JDBC 代码。
其他问题
我没有详细说明,例如用于管理您的 CA 证书文件的适当安全协议,或者例如通过从 JNDI server rather than hard-coding 获取 DataSource
对象来外部化您的连接信息。但希望上面的示例可以帮助您入门。