无法使用私有 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 错误预检缺少允许源标头)的主要内容,如果未能解决你的问题,请参考以下文章