无法使用私有 IP 地址连接到 GCP CloudSQL(CORS 错误预检缺少允许源标头)

Posted

技术标签:

【中文标题】无法使用私有 IP 地址连接到 GCP CloudSQL(CORS 错误预检缺少允许源标头)【英文标题】:Unable to connect to GCP CloudSQL using Private IP address (CORS error preflight missing allow origin header) 【发布时间】:2021-11-11 09:02:07 【问题描述】:

我正在使用 GCP Cloud SQL 实例来获取数据。当使用其公共 IP 地址访问此 SQL 实例时,连接正在发生并且数据是可见的。但由于安全限制,我只能通过私有 IP 地址访问它。

我按照 Google 文档中的说明对通过私有 IP 地址进行连接的代码进行了更改: (https://cloud.google.com/sql/docs/postgres/connect-app-engine-standard#private-ip_1) (https://cloud.google.com/vpc/docs/configure-serverless-vpc-access#java-8)

    ConnectionPoolContextListener.java 文件中:iptypes=Private added

config.addDataSourceProperty("ipTypes", "PRIVATE");

    appengine-web.xml 文件中:添加了无服务器 vpc 连接器元素
项目/PROJECTNAME/locations/europe-west1/connectors/CONNECTORNAME 全流量
    gitlab-ci.yml 文件中:添加了部署连接器服务的行

deploy_env 名称: 脚本:-gcloud app deploy src/main/webapp/WEB-INF/appengine-web.xml

这些更改不起作用并且进行的 API 调用失败并给出 CORS 错误(跨源资源共享错误预检缺少允许源头)(请参阅屏幕截图) UI CORS Error

应用引擎日志如下: com.zaxxer.hikari.pool.HikariPool throwPoolInitializationException: HikariPool-1 - 池初始化期间出现异常。 (HikariPool.java:587) org.postgresql.util.PSQLException:连接尝试失败。 ... 原因:java.io.IOException:连接被拒绝

使用公共 IP 地址时一切正常,也没有 CORS 错误。但是私有 IP 地址连接失败,不知道这里出了什么问题。

数据库连接代码:

private DataSource createConnectionPool() 
HikariConfig config = new HikariConfig();
config.setJdbcUrl(String.format("jdbc:postgresql://google/%s", 
DB_NAME));
config.setUsername(DB_USER);
config.setPassword(DB_PASS); 
config.addDataSourceProperty("socketFactory", 
"com.google.cloud.sql.postgres.SocketFactory");
config.addDataSourceProperty("cloudSqlInstance", 
CLOUD_SQL_CONNECTION_NAME);
config.addDataSourceProperty("ipTypes", "PRIVATE");
config.setMaximumPoolSize(10);
config.setMinimumIdle(5);
config.setConnectionTimeout(10000); // 10 seconds
config.setIdleTimeout(600000); // 10 minutes
config.setMaxLifetime(1800000); // 30 minutes
DataSource pool = new HikariDataSource(config);
return pool;

【问题讨论】:

只需勾选方框... VPC Access 连接器是在与 App Engine 实例相同的项目和相同区域中创建的,对吗? AppEngine 存在多久了?真的老了吗?检查网络页面,您没有看到“旧版”标记您的 App Engine 所在的网络。除非这些,包括一些连接代码会有所帮助(显然删除密码/用户信息,但连接字符串会很好,只是为了确保它的格式正确)。 哦,你的应用现在有 CORS 标头吗?还是它以前只是神奇地工作而现在却不是? VPC连接器与App引擎实例在同一区域。应用引擎网络未标记为旧版。尚未添加 CORS 标头。但是只有当我禁用公共 IP 地址访问并且在我启用公共 IP 后应用程序工作正常时,我才会收到 CORS 错误。我曾经尝试添加 CORS 标头,当时我遇到了 App 引擎版本流量迁移的问题,流量迁移失败。 CORS 错误是无关的,可能是由失败的 HTTP 请求引发的。真正的问题是,为什么您的连接被拒绝? 因此查看连接字符串(没有凭据)并了解您要连接的数据库类型会有所帮助(mysql、postgres 等)。 【参考方案1】:

我之前创建的 VPC 连接器有问题。我创建了一个新的 VPC 连接器,其网络和区域与 cloudsql 实例的网络和区域相同,并分配了一个 IP 地址范围,现在这个数据库连接正在发生,数据正在加载,CORS 错误已经消失。

因此,要通过 App 引擎的私有 IP 地址连接到 SQL 实例,我只需进行以下更改:

    创建无服务器 VPC 连接器。 在 appengine.yml 文件中添加 vpc-connector 元素 在 ConnectionPoolContextListener.java 文件中包含属性“iptypes”

【讨论】:

【参考方案2】:

这就是问题所在。连接字符串中有错误:

// Not correct
config.setJdbcUrl(String.format("jdbc:postgresql://google/%s", DB_NAME));

// Should be
config.setJdbcUrl(String.format("jdbc:postgresql:///%s", DB_NAME));

详情请参阅文档:https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory/blob/main/docs/jdbc-postgres.md#creating-the-jdbc-url。

【讨论】:

嗨@enocom,我在 JDBC URL 中进行了此更改,并根据此文档检查了其他属性,仍然是同样的错误。 我验证了这个作品。这就是我所做的:我从github.com/GoogleCloudPlatform/java-docs-samples/tree/master/… 开始。我在指向我的访问连接器的 appengine-web.xml 中添加了一个 vpc 访问连接器设置。然后我部署并看到一切正常。我建议通过相同的练习来找出可能缺少哪些细节。

以上是关于无法使用私有 IP 地址连接到 GCP CloudSQL(CORS 错误预检缺少允许源标头)的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSql 本地连接到远程服务器 GCP

无法通过 unix 套接字从托管在不同 GCP 项目中的 App Engine 柔性环境连接到 Cloud SQL

使用私有 IP 从不同 VPC 网络中的 GKE 集群连接到 Cloud SQL

从具有私有和公共 IP 的虚拟机连接到私有 IP 上的 Google Cloud SQL 实例失败

Spring GCP 服务未连接到 Cloud SQL 数据库

GCP - 将 Vertex.AI 连接到共享 VPC 的问题