尝试通过 JDBC 与 Postgres 进行 SSL 连接时出现 PSQLException“无法打开 SSL 根证书文件”

Bas*_*que 5 postgresql ssl datasource jdbc

在 Java 15 中,使用来自 jdbc.postgresql.org 的 PostgreSQL JDBC 驱动程序(版本 42.2.18,JDBC4.2)DataSource

\n
PGSimpleDataSource ds = new PGSimpleDataSource();\nds.setServerNames( new String[] { "my-server-address" } );\nds.setPortNumbers( new int[] { 25060 } );\nds.setSsl( true );\nds.setDatabaseName( "mydb" );\nds.setUser( "scott" );\nds.setPassword( "tiger" );\nthis.dataSource = ds;\n
Run Code Online (Sandbox Code Playgroud)\n

\xe2\x80\xa6代码Connection conn = this.dataSource.getConnection();抛出此异常:

\n
\n

org.postgresql.util.PSQLException:无法打开 SSL 根证书文件 /Users/basilbourque/.postgresql/root.crt。

\n
\n

我知道我的 Postgres 12 服务器设置为 SSL 连接,因为我的IntelliJ Ultimate具有数据库访问功能 ( DataGrip ),可以成功连接 SSL (TLS) 保护。

\n

DataSource那么我的JDBC 配置有什么问题呢?

\n

Bas*_*que 10

感谢pgjdbc 驱动程序的Github 问题页面,我找到了 davecramer 的这篇文章:

从 42.2.5 开始,ssl=true 意味着按照发行说明进行验证。如果您希望获得旧行为,请使用 sslmode=require

果然,替换ds.setSsl( true );ds.setSslMode( "require" );允许我的 JDBC 驱动程序通过DataSource.

        PGSimpleDataSource ds = new PGSimpleDataSource();
        ds.setServerNames( new String[] { "my-server-address" } );
        ds.setPortNumbers( new int[] { 25060 } );
        ds.setSslMode( "require" );  // Replaces: ds.setSsl( true );
        ds.setDatabaseName( "mydb" );
        ds.setUser( "scott" );
        ds.setPassword( "tiger" );
        this.dataSource = ds;
Run Code Online (Sandbox Code Playgroud)

我不知道这些 SSL/TLS 相关选项实际上在做什么,但这对我连接到我的 DigitalOcean 管理的 Postgres 数据库服务器很有用。

以下代码片段现在可以成功运行:

        try
                (
                        Connection conn = this.dataSource.getConnection() ;
                        Statement stmt = conn.createStatement() ;
                )
        {
            String sql =
                    """
                    SELECT uuid_generate_v1()
                    ;
                    """;
            try (
                    ResultSet rs = stmt.executeQuery( sql ) ;
            )
            {
                while ( rs.next() )
                {
                    UUID uuid = rs.getObject( 1 , UUID.class );
                    System.out.println( "uuid = " + uuid );
                }
            }
        }
        catch ( SQLException e )
        {
            e.printStackTrace();
        }
Run Code Online (Sandbox Code Playgroud)

  • 通过这些选项,PostgreSQL 使用加密通信,但不会尝试验证服务器的真实性。因此您可能会成为中间人攻击的牺牲品。如果不担心的话,那么您的设置就很好。 (2认同)