升级AWS Aurora证书rds-ca-ecc384-g1后SpringBoot无法连PostgreSQL
AWS Aurora证书更新后SpringBoot应用无法连接PostgreSQL
我有一个部署在AWS BeanStalk上的SpringBoot应用,此前通过以下配置可以正常连接PostgreSQL,但在将AWS Aurora证书更新为rds-ca-ecc384-g1后,应用无法建立连接,出现SSL握手失败错误。
原数据库连接配置
spring.datasource.url=jdbc:postgresql://{SUBDOMAIN}.us-east-2.rds.amazonaws.com:5432/{DATABASE_NAME} spring.datasource.username={USER} spring.datasource.password={PASSWORD} spring.datasource.hikari.maximum-pool-size=2 spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation= true spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.PostgreSQLDialect spring.jpa.properties.hibernate.show_sql=true spring.jpa.open-in-view=false spring.jpa.hibernate.ddl-auto=create
应用报错信息
org.postgresql.util.PSQLException: SSL error: Received fatal alert: handshake_failure at org.postgresql.ssl.MakeSSL.convert(MakeSSL.java:43) ~[postgresql-42.5.4.jar!/:42.5.4] at org.postgresql.core.v3.ConnectionFactoryImpl.enableSSL(ConnectionFactoryImpl.java:620) ~[postgresql-42.5.4.jar!/:42.5.4] at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:191) ~[postgresql-42.5.4.jar!/:42.5.4] at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:258) ~[postgresql-42.5.4.jar!/:42.5.4] at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:54) ~[postgresql-42.5.4.jar!/:42.5.4] at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:253) ~[postgresql-42.5.4.jar!/:42.5.4] at org.postgresql.Driver.makeConnection(Driver.java:434) ~[postgresql-42.5.4.jar!/:42.5.4] at org.postgresql.Driver.connect(Driver.java:291) ~[postgresql-42.5.4.jar!/:42.5.4] at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138) ~[HikariCP-5.0.1.jar!/:na] at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:359) ~[HikariCP-5.0.1.jar!/:na] at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:201) ~[HikariCP-5.0.1.jar!/:na] at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:470) ~[HikariCP-5.0.1.jar!/:na] at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:561) ~[HikariCP-5.0.1.jar!/:na] at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:100) ~[HikariCP-5.0.1.jar!/:na] at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112) ~[HikariCP-5.0.1.jar!/:na] at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) ~[hibernate-core-6.1.7.Final.jar!/:6.1.7.Final] at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:284) ~[hibernate-core-6.1.7.Final.jar!/:6.1.7.Final] at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:177) ~[hibernate-core-6.1.7.Final.jar!/:6.1.7.Final] at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:36) ~[hibernate-core-6.1.7.Final.jar!/:6.1.7.Final] at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:119) ~[hibernate-core-6.1.7.Final.jar!/:6.1.7.Final] at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:255) ~[hibernate-core-6.1.7.Final.jar!/:6.1.7.Final] at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:230) ~[hibernate-core-6.1.7.Final.jar!/:6.1.7.Final] at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) ~[hibernate-core-6.1.7.Final.jar!/:6.1.7.Final] at org.hibernate.boot.model.relational.Database.<init>(Database.java:44) ~[hibernate-core-6.1.7.Final.jar!/:6.1.7.Final] at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.getDatabase(InFlightMetadataCollectorImpl.java:218) ~[hibernate-core-6.1.7.Final.jar!/:6.1.7.Final] at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.java:191) ~[hibernate-core-6.1.7.Final.jar!/:6.1.7.Final] at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:138) ~[hibernate-core-6.1.7.Final.jar!/:6.1.7.Final] at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1348) ~[hibernate-core-6.1.7.Final.jar!/:6.1.7.Final] at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1419) ~[hibernate-core-6.1.7.Final.jar!/:6.1.7.Final] at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75) ~[spring-orm-6.0.11.jar!/:6.0.11] at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:376) ~[spring-orm-6.0.11.jar!/:6.0.11] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-6.0.11.jar!/:6.0.11] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[spring-orm-6.0.11.jar!/:6.0.11] at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:352) ~[spring-orm-6.0.11.jar!/:6.0.11] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1817) ~[spring-beans-6.0.11.jar!/:6.0.11] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1766) ~[spring-beans-6.0.11.jar!/:6.0.11] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598) ~[spring-beans-6.0.11.jar!/:6.0.11] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[spring-beans-6.0.11.jar!/:6.0.11] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[spring-beans-6.0.11.jar!/:6.0.11] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.0.11.jar!/:6.0.11] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[spring-beans-6.0.11.jar!/:6.0.11] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.0.11.jar!/:6.0.11] at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1155) ~[spring-context-6.0.11.jar!/:6.0.11] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932) ~[spring-context-6.0.11.jar!/:6.0.11] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:608) ~[spring-context-6.0.11.jar!/:6.0.11] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.0.10.jar!/:3.0.10] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732) ~[spring-boot-3.0.10.jar!/:3.0.10] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434) ~[spring-boot-3.0.10.jar!/:3.0.10] at org.springframework.boot.SpringApplication.run(SpringApplication.java:310) ~[spring-boot-3.0.10.jar!/:3.0.10] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1304) ~[spring-boot-3.0.10.jar!/:3.0.10] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1293) ~[spring-boot-3.0.10.jar!/:3.0.10] at com.app.Main.main(Main.java:18) ~[classes!/:1.0-SNAPSHOT] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na] at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[main-1.0-SNAPSHOT.jar:1.0-SNAPSHOT] at org.springframework.boot.loader.Launcher.launch(Launcher.java:95) ~[main-1.0-SNAPSHOT.jar:1.0-SNAPSHOT] at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[main-1.0-SNAPSHOT.jar:1.0-SNAPSHOT] at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) ~[main-1.0-SNAPSHOT.jar:1.0-SNAPSHOT] Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131) ~[na:na] at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117) ~[na:na] at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:365) ~[na:na] at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:293) ~[na:na] at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:204) ~[na:na] at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:172) ~[na:na] at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1510) ~[na:na] at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1425) ~[na:na] at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:455) ~[na:na] at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:426) ~[na:na] at org.postgresql.ssl.MakeSSL.convert(MakeSSL.java:41) ~[postgresql-42.5.4.jar!/:42.5.4] ... 59 common frames omitted
手动psql连接报错
$ PGSSLMODE=verify-full psql -h {SUBDOMAIN}.us-east-2.rds.amazonaws.com -p 5432 -U {USER} -W {DATABASE_NAME} Password: psql: error: connection to server at "{SUBDOMAIN}.us-east-2.rds.amazonaws.com" (10.0.156.184), port 5432 failed: root certificate file "/home/ec2-user/.postgresql/root.crt" does not exist Either provide the file or change sslmode to disable server certificate verification.
解决方法
给SpringBoot应用配置新CA证书
更新Aurora证书后,应用的JVM默认信任存储里没有rds-ca-ecc384-g1的根证书,导致SSL握手失败。可以通过两种方式修复:
在JDBC URL中直接指定证书
把rds-ca-ecc384-g1.pem证书文件放到应用的src/main/resources目录下,然后修改JDBC URL:spring.datasource.url=jdbc:postgresql://{SUBDOMAIN}.us-east-2.rds.amazonaws.com:5432/{DATABASE_NAME}?sslmode=verify-full&sslrootcert=classpath:rds-ca-ecc384-g1.pem导入证书到JVM信任存储
如果不想修改URL,可以把证书导入到应用使用的JVM信任存储:# 下载证书 curl -o rds-ca-ecc384-g1.pem https://truststore.pki.rds.amazonaws.com/us-east-2/rds-ca-ecc384-g1.pem # 导入到JVM信任存储(路径根据你的JDK安装位置调整) keytool -importcert -file rds-ca-ecc384-g1.pem -alias rds-ecc-ca -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit注意:如果是AWS BeanStalk环境,可能需要通过自定义配置脚本完成证书导入,或者使用应用的自定义信任存储并在启动参数中指定。
修复psql命令行连接
psql报错是因为找不到指定路径的根证书,只需把证书放到要求的位置:
mkdir -p ~/.postgresql/ curl -o ~/.postgresql/root.crt https://truststore.pki.rds.amazonaws.com/us-east-2/rds-ca-ecc384-g1.pem chmod 600 ~/.postgresql/root.crt
执行以上命令后再重新连接即可。
额外检查点
- 确认PostgreSQL JDBC驱动版本:你的版本42.5.4已经支持ECC证书,若仍有问题可以尝试升级到最新稳定版。
- 检查JDK版本:JDK 8u161及以上默认支持ECC算法,确保BeanStalk使用的JDK版本符合要求。
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

