Flutter Google Places API 授权错误

问题描述 投票:0回答:1

我有一个 Flutter 应用程序,它利用 Google 地图显示地图并调用 Places API 以根据用户的位置检索附近的商店。在开发过程中,我没有限制 API 密钥,但现在我想转向生产,我限制了 Android 和 iOS 密钥

以下是我如何调用 Places API:

final String apiUrl =
    "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${cords.latitude}%2C${cords.longitude}&radius=$radius&type=$type&key=$apiKey";
final response = await http.get(Uri.parse(apiUrl));

我尝试限制 iOS 和 Android 的 API 密钥(每个应用程序 1 个密钥)。地图显示正确,但对地方 API 的调用返回以下错误:

{
   "error_message" : "This IP, site or mobile application is not authorized to use this API key. Request received from IP address x.x.x.x, with empty referer",
   "html_attributions" : [],
   "results" : [],
   "status" : "REQUEST_DENIED"
}

经过一段时间的搜索,我发现了一个 Stack Overflow 帖子,建议一些 google 地图 API 被设计为从后端系统调用,而不是直接从前端调用。以下是该帖子的链接供参考:Android Google Maps Direction Api - Api key limit notworking

这让我想到也许我也会遇到这种情况。根据用户提供的链接,事实证明它实际上是......(如果我弄错了,请告诉我)

我应该对不同的地图产品使用哪些密钥或凭据?

我正在考虑修改调用 Places API 的方式。由于我已经使用 Firebase,因此我正在考虑触发 Cloud Function 来进行 Places API 调用,然后将 JSON 响应转发到客户端电话。但是,我不确定是否应该限制云功能的 API 密钥。

我的问题是:

  • 根据提供的 Stack Overflow 帖子,我切换到云函数来调用 Places API 的理由是否正确?
  • 考虑到安全问题,我是否应该限制云功能的 API 密钥?

如果您相信我可以用另一种方式解决这个问题,请告诉我,我还注意到表格上有适用于 android 和 iOS 的 Places SDK 的条目,可以限制为应用程序,但我不知道它是否适合我案例是因为我正在使用 flutter。

需要澄清的事情:

  • 密钥是正确的,当我关闭限制时它会起作用
  • 计费已启用
  • places api 也已启用
  • 还有剩余名额

任何建议或见解将不胜感激。预先感谢您。

flutter google-maps google-places-api
1个回答
0
投票

我最终所做的实际上是使用可调用的云函数,因为我已经在使用 firebase 并且实现了 App Check 以确保只有我的应用程序可以触发该函数并确保 api 密钥的安全,我使用了谷歌云秘密管理器.

这也是一个很好的做法,建议将其限制为您要使用的特定 API

对于任何对如何保护敏感信息感兴趣的人,Cloud Functions for Firebase 与 Google Cloud Secret Manager 集成。

https://firebase.google.com/docs/functions/config-env?gen=2nd#create-secret

export const fetchFromGoogleMaps = functions.onCall({
  secrets: ["secret_name"],
  enforceAppCheck: true,
}, async (request) => {
  const apiKey = process.env.secret_name;

  const apiUrl = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${latitude}%2C${longitude}&radius=${radius}&type=${type}&key=${apiKey}`;

  return await axios.default.get(apiUrl).then((apiResponse) => {
    // ...
  }).catch((error) => {
    // handle the error
  });

© www.soinside.com 2019 - 2024. All rights reserved.