简体   繁体   English

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

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

I am trying the managed database service on DigitalOcean.com , having created a Postgres instance .我正在DigitalOcean.com上尝试托管数据库服务,并创建了一个 Postgres 实例

Digital Ocean defaults to requiring remote connections be made with SSL (actually TLS ) encryption. Digital Ocean 默认要求使用SSL (实际上是TLS )加密进行远程连接。

How does one configure a JDBC DataSource implementation for providing connections to such a database server?如何配置JDBC DataSource实现以提供与此类数据库服务器的连接?

This Question is similar to Produce a DataSource object for Postgres JDBC, programmatically but adds the specific elements of SSL/TLS encryption and using a managed database remotely.此问题类似于Produce a DataSource object for Postgres JDBC,以编程方式添加 SSL/TLS 加密的特定元素并远程使用托管数据库。

Obtaining a DataSource implementation获取DataSource实现

Usually your JDBC driver provides an implementation of javax.sql.DataSource .通常您的JDBC 驱动程序提供javax.sql.DataSource的实现。

For more details, see my Answer to a similar Question.有关更多详细信息,请参阅我对类似问题的回答

PGSimpleDataSource

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

Instantiate an object of type PGSimpleDataSource , then call setter methods to provide all the info needed to connect to your database server.实例化一个 PGSimpleDataSource 类型的PGSimpleDataSource ,然后调用 setter 方法来提供连接到数据库服务器所需的所有信息。 The web page on the DigitalOcean site lists all these pieces of info for your particular database instance. DigitalOcean 网站上的 web 页面列出了您特定数据库实例的所有这些信息。

Basically this:基本上是这样的:

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

Plural server names and port numbers复数服务器名称和端口号

Unfortunately, the singular version of the methods setServerName and setPortNumber are deprecated.不幸的是, setServerNamesetPortNumber方法的单一版本已被弃用。 While annoying, we should probably use the plural version of those methods ( setServerNames & setPortNumbers ) that each take an array.虽然烦人,但我们可能应该使用这些方法的复数版本( setServerNamessetPortNumbers ),它们每个都采用一个数组。 We populate a pair of single-element arrays, String[] and int[] , with our server's address and port number using array literals:我们使用数组文字填充一对单元素 arrays、 String[]int[] ,以及我们的服务器地址和端口号

  • { "your-server-address-goes-here" } {“你的服务器地址去这里”}
  • { your-port-number-goes-here } {你的端口号去这里}
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 encryption SSL/TLS 加密

Lastly we need to add info for the SSL/TLS encryption addressed in the Question.最后,我们需要为问题中提到的 SSL/TLS 加密添加信息。

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

You would think we would call the setSsl method and pass true .你会认为我们会调用setSsl方法并传递true But, no.但不是。 While counter-intuitive, setting that to true will cause your connection attempts to fail.虽然违反直觉,但将其设置为 true 会导致您的连接尝试失败。 I do not know why that is.我不知道为什么会这样。 But trial-and-error led me to avoid that call.但是反复试验使我避免了那个电话。

CA certificate CA 证书

In order for your client-side Java app to initiate the SSL/TLS connection, the JDBC driver must have access to the CA certificate used by Digital Ocean.为了让您的客户端 Java 应用程序启动 SSL/TLS 连接,JDBC 驱动程序必须有权访问 Digital Ocean 使用的CA 证书 On your Digital Ocean admin page, click the Download CA certificate link to download a tiny text file.在您的 Digital Ocean 管理页面上,单击Download CA certificate链接以下载一个小文本文件。 That file will be named ca-certificate.crt .该文件将命名为ca-certificate.crt

We need to feed the text of that file to our JDBC driver as a string.我们需要将该文件的文本作为字符串提供给我们的 JDBC 驱动程序。 Do the following to load the file into a text string.执行以下操作以将文件加载到文本字符串中。

// 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." ); }

Pass that CA certificate text to your JDBC driver with a call to DataSource::setSslCert .通过调用DataSource::setSslCert将该 CA 证书文本传递给您的 JDBC 驱动程序。 Note that we are not calling setSslRootCert .请注意,我们没有调用setSslRootCert Do not mix up the two similarly-named methods.不要混淆这两种名称相似的方法。

dataSource.setSslCert( cert );

Testing the connection测试连接

Lastly, we can use the configured DataSource object to make a connection to the database.最后,我们可以使用配置的DataSource object 来连接数据库。 That code will look like this:该代码将如下所示:

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

Complete example code完整的示例代码

Putting all that together, see something like this.把所有这些放在一起,看看这样的东西。

// 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();
}

Trusted source可信来源

When creating your Postgres instance on DigitalOcean.com, you will be offered the ability to restrict incoming connection requests.在 DigitalOcean.com 上创建 Postgres 实例时,您将能够限制传入的连接请求。 You can specify a single IP address to be expected by the Postgres server, a “trusted source” in Digital Ocean's lingo.您可以指定 Postgres 服务器预期的单个 IP 地址,这是 Digital Ocean 行话中的“可信来源”。 Any hackers attempting to connect to your Postgres server will be ignored as they originate from other IP addresses.任何试图连接到您的 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. 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. If you are running your Java code from the same computer, use that same IP number as your single trusted source.如果您在同一台计算机上运行 Java 代码,请使用相同的 IP 编号作为您的单一可信来源。

Otherwise, type in the IP address of the computer running your Java JDBC code.否则,输入运行 Java JDBC 代码的计算机的 IP 地址。

Other issues其他问题

I have not addressed elaborations, such as proper security protocols to use to manage your CA certificate file, or such as externalizing your connection info by getting a DataSource object from a JNDI server rather than hard-coding .我没有详细说明,例如用于管理您的 CA 证书文件的适当安全协议,或者例如通过从JNDI服务器获取DataSource object 而不是硬编码来外部化您的连接信息。 But hopefully the examples above help you get started.但希望上面的示例可以帮助您入门。

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

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