首页 > 解决方案 > Google 地图 - 直接从 javascript 调用 API 与使用 SDK

问题描述

我正在尝试从我的 javascript 代码中使用Google Places API 。

(假设所有其他事情 - api 密钥、从 google 控制台启用 API等都已经完成)。

当我尝试直接从我的 javascript 访问 Places API 时,它给了我一个 CORS 错误,我认为这是因为我的域未在 Places API 中列入白名单。

为了避免这种情况,建议的方法是使用Javascript Maps SDK。SDK 不是一个 npm 模块,它是一个托管的 JS 文件,与 Places API 在同一个域中。

我想了解的是这个用 Javascript 编写的 SDK 如何调用 Places API 并且不会出现 CORS 错误。
这是否与 Maps SDK 和 Places API 来自同一个域的事实有关?
这些api调用不应该在我的域的上下文中执行并由于CORS而被阻止吗?
如果 SDK 是 npm 包,它还能工作吗?

SDK 进行的 api 调用与 Places API 并不完全相同,但在同一个域中。

/maps/api/place/autocomplete/json?input=Ben&key=KEY

对比

/maps/places/api/js/AutocompleteService.GetPredicitons

我已经尝试直接从我的 javascript 调用 /maps/places/api/js/AutocompleteService.GetPredicitons ,但它也给了我 CORS 错误。

标签: javascriptgoogle-mapscors

解决方案


TL;博士; google sdk 使用 jsonp,通过使用脚本标签进行调用并指定回调。这与被同源策略阻止的 XHR 请求不同。

解释:

脚本的托管位置无关紧要,因为它是在您的域的上下文中执行的,因此浏览器进行的任何 api 调用都将作为您的域而不是托管脚本的域。

这意味着,如果 SDK 正在从 maps.googleapis.com/maps/... 调用端点,实际上它确实这样做了,那么请求应该以我的域作为我的域,并且应该给出 CORS 错误,但它仍然是返回数据。

经过进一步检查,我发现 SDK 没有发出 xhr 请求(由于同源策略而被阻止),而是创建了一个脚本标签并处理服务器返回的响应。它使用 jsonp 通过在 url 中提供回调来执行此操作,以便服务器发送包含在该回调中的响应,并且一旦脚本被下载并执行,它就会运行该函数并且 sdk 现在可以处理数据。

关于安全性和一般理解的几点:

  1. sdk 需要有一个 api 密钥,它与每个 api 调用一起发送。因此,如果您通过传入您的密钥(看起来像这样:https ://maps.googleapis.com/maps/api/js?key=KEY&libraries=places )从托管 url 下载 sdk 并分发它,您基本上会分发 sdk 脚本,其中包含硬编码的密钥。(当然,如果您对您的 api 密钥设置了限制,这不会有任何特定的安全隐患,您应该这样做,因为您的密钥在网络调用中对您的用户是可见的)

  2. 即使在我了解 sdk 正在使用 jsonp 工作并且我能够进行完全相同的 api 调用之后,当我更改了我需要建议的查询文本并且没有更改任何其他内容(所有其他参数都相同)时,调用仍然以 403 失败。这是因为,sdk 似乎在参数中发送了一个令牌,该参数以某种方式从查询文本中派生而来。因此,绕过 sdk 并自己创建这些调用并不容易,因为您需要弄清楚令牌生成算法。

  3. 最重要的是,由于我启用了Referer only api key security,所以无论如何谷歌都不会允许任何其他引用者使用我的密钥,即使该密钥在我的应用程序用户的网络选项卡中可见。


推荐阅读