1. 介绍
在数据库管理领域,确保应用与数据库间的安全通信至关重要。本文将介绍如何通过JDBC和Spring Boot建立PostgreSQL的SSL连接。我们将涵盖服务器配置、证书处理和多种连接方式,助你快速实现安全数据库通信。
2. PostgreSQL配置
首先需要配置PostgreSQL服务器支持SSL连接。确保已准备好根CA证书、服务器证书和私钥文件。修改服务器配置文件postgresql.conf
,添加证书路径:
...
ssl = on
ssl_ca_file = '/opt/homebrew/var/postgresql@14/rootCA.crt'
ssl_cert_file = '/opt/homebrew/var/postgresql@14/localhost.crt'
#ssl_crl_file = ''
#ssl_crl_dir = ''
ssl_key_file = '/opt/homebrew/var/postgresql@14/localhost.key'
...
接着修改客户端配置文件pg_hba.conf
,在IPv4部分添加:
...
# IPv4 local connections:
hostssl all all 0.0.0.0/0 cert
...
⚠️ 确保证书文件路径正确且权限设置合理,否则会导致连接失败。
3. Maven配置
在pom.xml
中添加PostgreSQL JDBC驱动依赖:
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.3</version>
</dependency>
我们使用最新版驱动以支持pkcs-12客户端证书格式。
4. 通过JDBC直接连接
建立SSL连接需要客户端证书(需使用与服务器证书相同的根CA签发)。重要:JDBC无法直接使用原始私钥,需先转换为pkcs-8格式:
openssl pkcs8 -topk8 -inform PEM -outform DER -in certs/pg_client.key -out certs/pg_client.pk8 -nocrypt
创建PgJdbc
类实现连接测试:
public class PgJdbc {
public void checkConnectionSsl(String url, String username, String password, Map<String, String> extraProps) {
Properties props = new Properties();
props.putAll(extraProps);
props.put("username", username);
props.put("password", password);
props.put("sslmode", "verify-ca");
props.put("ssl", "true");
try (Connection connection = DriverManager.getConnection(url, props)) {
if (!connection.isClosed()) {
connection.close();
}
System.out.println("Connection was successful");
} catch (SQLException e) {
System.out.println("Connection failed");
}
}
// ...
}
在main
方法中测试连接:
public class PgJdbc {
// ...
public static void main(String[] args) {
PgJdbc pg = new PgJdbc();
String url = "jdbc:postgresql://localhost:5432/testdb";
String username = "postgres";
String password = "password";
String BASE_PATH = Paths.get("certs")
.toAbsolutePath()
.toString();
Map<String, String> connectionProperties = Map.of(
"sslcert", BASE_PATH.concat("/pg_client.crt"),
"sslkey", BASE_PATH.concat("/pg_client.pk8"),
"sslrootcert", BASE_PATH.concat("/root.crt"));
System.out.println("Connection without keystore and truststore");
pg.checkConnectionSsl(url, username, password, connectionProperties);
}
}
执行测试:
$ mvn clean compile -q exec:java -Dexec.mainClass="com.baeldung.pgoverssl.PgJdbc"
Connection was successful
✅ 连接成功建立!这种方式简单直接,适合快速验证。
5. 通过JDBC使用密钥库连接
也可使用Java密钥库(keystore)和信任库(truststore)建立连接。步骤如下:
将证书和私钥转换为pkcs-12格式:
$ openssl pkcs12 -export -in certs/pg_client.crt -inkey certs/pg_client.key -out certs/pg_client.p12 -name postgres
创建密钥库:
$ keytool -importkeystore -destkeystore certs/pg_client.jks -srckeystore certs/pg_client.p12 -srcstoretype pkcs12 Importing keystore certs/pg_client.p12 to certs/pg_client.jks... Enter destination keystore password: ... Import command completed: 1 entries successfully imported, 0 entries failed or cancelled
创建信任库:
$ keytool -import -alias server -file certs/root.crt -keystore certs/truststore.jks -storepass password ... Certificate was added to keystore
修改main
方法使用密钥库:
public class PgJdbc {
// ...
public static void main(String[] args) {
// ...
System.setProperty("javax.net.ssl.keyStore", BASE_PATH.concat("/pg_client.jks"));
System.setProperty("javax.net.ssl.keyStorePassword", "password");
System.setProperty("javax.net.ssl.trustStore", BASE_PATH.concat("/truststore.jks"));
System.setProperty("javax.net.ssl.trustStorePassword", "password");
System.out.println("\nConnection using keystore and truststore");
pg.checkConnectionSsl(url, username, password, Map.of("sslfactory", "org.postgresql.ssl.DefaultJavaSSLFactory"));
}
}
执行测试:
Connection using keystore and truststore
Connection was successful
✅ 同样成功连接!这种方式更适合生产环境,便于统一管理证书。
6. 通过Spring Boot连接
在Spring Boot应用中配置SSL连接同样简单。添加依赖:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.3</version>
</parent>
// ...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
创建启动类:
@SpringBootApplication
public class PgSpringboot {
public static void main(String[] args) {
SpringApplication.run(PgSpringboot.class, args);
}
}
配置application.yaml
:
spring:
application:
name: postgresqlssltest
datasource:
url: jdbc:postgresql://localhost:5432/testdb?ssl=true&sslmode=verify-ca&sslrootcert=certs/root.crt&sslcert=certs/pg_client.crt&sslkey=certs/pg_client.pk8
username: postgres
password: "password"
driver-class-name: org.postgresql.Driver
jpa:
hibernate:
ddl-auto: update
database-platform: org.hibernate.dialect.PostgreSQLDialect
启动应用测试连接:
$ mvn clean compile -q exec:java -Dexec.mainClass="com.baeldung.pgoverssl.PgSpringboot" -Dspring.config.location=classpath:./pgoverssl/application.yaml
...
2024-07-04T21:41:17.552+01:00 INFO 458 --- [postgresqlssltest] [ringboot.main()] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2024-07-04T21:41:18.290+01:00 INFO 458 --- [postgresqlssltest] [ringboot.main()] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Added connection org.postgresql.jdbc.PgConnection@4e331d3d
2024-07-04T21:41:18.291+01:00 INFO 458 --- [postgresqlssltest] [ringboot.main()] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
...
✅ Spring Boot成功建立SSL连接!配置集中在YAML文件中,维护更方便。
7. 总结
本文详细介绍了通过SSL连接PostgreSQL的多种方式:
- ✅ 直接使用证书和私钥(适合快速验证)
- ✅ 使用Java密钥库(适合生产环境)
- ✅ Spring Boot集成(简化配置)
关键点总结:
- 服务器需正确配置SSL证书
- 客户端证书需与服务器使用相同根CA
- 私钥格式转换是常见踩坑点
- Spring Boot通过URL参数简化配置
完整示例代码可在GitHub获取。根据实际场景选择合适方案,确保数据库通信安全可靠。