Spring Boot配置resources目录下私钥至application.properties报错求解决
解决Spring Boot中PostgreSQL数据源无法读取classpath下私钥文件的问题
问题根源
PostgreSQL JDBC驱动不支持在sslkey参数中直接使用classpath:前缀,它仅识别本地文件系统的绝对/相对路径,所以直接在数据源URL中配置classpath:client-key.pk8会导致文件读取失败。
解决方案
方案1:将classpath资源复制到临时文件后引用
编写启动时的处理器,把Resources目录下的私钥文件复制到临时目录,再用临时文件路径配置数据源:
import org.springframework.boot.context.event.ApplicationStartedEvent; import org.springframework.context.event.EventListener; import org.springframework.core.io.ClassPathResource; import org.springframework.stereotype.Component; import java.io.File; import java.io.IOException; import java.nio.file.Files; @Component public class SslKeyTempHandler { public static String TEMP_SSL_KEY_PATH; @EventListener(ApplicationStartedEvent.class) public void copySslKeyToTemp() throws IOException { ClassPathResource keyResource = new ClassPathResource("client-key.pk8"); File tempKeyFile = File.createTempFile("client-key", ".pk8"); tempKeyFile.deleteOnExit(); // 程序退出自动清理临时文件 Files.copy(keyResource.getInputStream(), tempKeyFile.toPath()); TEMP_SSL_KEY_PATH = tempKeyFile.getAbsolutePath(); } }
修改application.properties中的数据源URL,使用占位符引用临时文件路径:
spring.datasource.url=jdbc:postgresql://x.x.x.x:5432/test?ssl=true&sslmode=verify-ca&sslrootcert=/etc/test/server-ca.pem&sslcert=/etc/test/client-cert.pem&sslkey=${com.example.SslKeyTempHandler.TEMP_SSL_KEY_PATH}
方案2:自定义数据源配置,手动设置SSL参数
绕过URL配置,直接创建PostgreSQL数据源实例,手动处理私钥文件:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.postgresql.ds.PGSimpleDataSource; import javax.sql.DataSource; import java.io.File; import java.io.IOException; import java.nio.file.Files; @Configuration public class PostgresDataSourceConfig { @Bean public DataSource postgresDataSource() throws IOException { PGSimpleDataSource dataSource = new PGSimpleDataSource(); dataSource.setServerName("x.x.x.x"); dataSource.setPortNumber(5432); dataSource.setDatabaseName("test"); dataSource.setSsl(true); dataSource.setSslmode("verify-ca"); dataSource.setSslrootcert("/etc/test/server-ca.pem"); dataSource.setSslcert("/etc/test/client-cert.pem"); // 处理classpath下的私钥文件 ClassPathResource keyResource = new ClassPathResource("client-key.pk8"); File tempKeyFile = File.createTempFile("client-key", ".pk8"); tempKeyFile.deleteOnExit(); Files.copy(keyResource.getInputStream(), tempKeyFile.toPath()); dataSource.setSslkey(tempKeyFile.getAbsolutePath()); return dataSource; } }
此时application.properties无需配置spring.datasource.url,可根据需要保留其他数据源相关配置(如用户名密码)。
内容的提问来源于stack exchange,提问作者Aditya Rewari
相关产品推荐
相关产品推荐

