Flutter中的安全性:google_maps_Flutter需要API密钥,但如何安全地提供它们



这个问题怎么不是的重复

虽然@MrUpsidedown在评论部分提供了一些相关的问题,但没有一个真正回答我在这里试图强调的部分:如何安全地提供API密钥

在阅读了所有相关问题的答案后,我倾向于自己写一个答案。

上下文

我是一个非常新鲜的Flutter开发人员,试图将谷歌地图集成到一个演示应用程序中。

为了节省时间,我决定尝试一下我能找到的最受欢迎的谷歌地图小工具库,即google_maps_flutter。该库的简洁文档显示了Android和iOS的使用示例,并说明了API密钥是作为代码库的一部分内联提供的:

import UIKit
import Flutter
import GoogleMaps
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GMSServices.provideAPIKey("YOUR KEY HERE") // <------------------------------------  O--пп
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
<manifest ...
<application ...
<meta-data android:name="com.google.android.geo.API_KEY"
android:value="YOUR KEY HERE"/>  <--------------------------------------  O--пп

大多数开发人员都知道API密钥必须安全存储。库文档中的代码不适合生产应用程序。谷歌地图平台文档明确警告不要使用硬编码的API密钥:

不要在代码中直接嵌入API密钥或签名机密。

不要将API密钥或签名机密存储在应用程序源树中的文件中。

问题

如何以正确、安全的方式使用此软件包?这可能吗?

我经常听到一个反复出现的想法:客户端应用程序不能存储API密钥(和类似的机密/凭据),因为它可能被恶意用户控制、操纵或反向工程";如果是这种情况,这是否意味着只要google_maps_flutter包需要明确提供Google Maps API密钥,我就必须考虑它本身的不安全性?

我也知道API密钥限制。我肯定会使用它,但在我看来,它只是减少了";爆破半径";如果API密钥被泄露。然而,我看不出这是如何防止API密钥泄露和第三方滥用的。

P.S

起初,我想更广泛地提出我的问题:有没有一种方法可以在移动平台(Android和iOS)上安全地传递、存储和消费秘密

以下是我的研究结论。

客户端设备是一个未受信任的环境

API密钥在客户端设备上可能不安全。从安全角度来看,客户端设备应被视为已损坏。

因此,以下每种方法都是不安全

  • 将API密钥直接存储在应用程序代码中。用户可以反编译应用程序,在调试器下运行应用程序等,并读取API密钥。

  • 将API密钥间接存储在应用程序中。通过环境变量提供API键并没有什么不同。密钥被印在构建的应用程序的工件中,并且与前面的方法一样可读。

  • 从受控服务向应用程序提供API密钥。用户可以像篡改导致从远程服务器接收密钥时拦截密钥一样扰乱应用程序。换言之,经典的中场进攻。

在理想的情况下,API密钥永远不会离开服务器

是的,你没听错。您的API密钥应该存在于只有您可以访问的服务中。该服务应该作为应用程序正在进行的所有上游API调用的代理。您不会将密钥暴露给客户端设备,因此它们不会从设备的环境中被盗。

然而,一个新的问题立即出现:如何限制对API端点的访问?这是一个悬而未决的问题,超出了这个答案的范围。我想注意的是,如果您为您的服务添加自己的API密钥,这在某种程度上会导致鸡或蛋的问题。尽管如此,拥有API密钥是向前迈出的一步,因为您可以抑制来自特定客户端的客户端请求。换句话说,你要确保你能控制一切,并且不会超过上游服务(如谷歌地图API)的配额。

然而,我不知道你如何可靠地识别来电者是你的应用(如果你需要的话)。如果我理解正确的话,应用程序id是不可靠的,因为上一节——客户端设备不可信。

关于google_maps_flutter

google_maps_flutter库仅在其文档中通过在应用程序中对API密钥进行硬编码来演示这些密钥的供应(请参见附录1)。这是不安全的。

正如有人在flutter的GitHub问题部分注意到的那样,google_maps_flutter不建议在生产环境的应用程序中对API密钥进行硬编码。然而,它没有说明或建议API密钥还可以从哪里提供。

更重要的是,它没有显示如何将代理服务器的响应/数据馈送到小部件本身,这是一个巨大的问题。

有人建议我使用谷歌地图API服务本身来限制API密钥。以下是Android和iOS的这些限制:

安卓应用

添加您的包名称和SHA-1签名证书指纹,以限制您的Android应用程序的使用。

iOS应用

使用您提供的捆绑包标识符接受iOS应用程序的请求。

我看不出它是如何作为一种可靠的工具工作的。客户手机上的SHA-1密钥和捆绑包标识符不能被篡改吗?!(我相信,他们可以。)

原始问题的答案

  1. 看起来今天库的使用者不得不使用不可靠的密钥泄漏缓解技术。要么大多数Flutter开发人员不想制造足够的噪音来解决问题,要么一开始就不理解这个问题,要么就放弃了让它正常工作的想法
  2. 目前,似乎不可能以安全的方式使用google_maps_flutter,这将避免API密钥泄露
  3. 如果该库为开发人员提供了一种将谷歌地图的响应/数据直接输入到小部件中的方法,情况就会发生变化,但我没有看到任何信息表明这是可观察的未来的计划变化

附录1

Android

在应用程序清单android/app/src/main/AndroidManifest.xml中指定您的API密钥:

<manifest ...
<application ...
<meta-data android:name="com.google.android.geo.API_KEY"
android:value="YOUR KEY HERE"/>

iOS

在应用程序代理ios/Runner/AppDelegate.m:中指定您的API密钥

#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
#import "GoogleMaps/GoogleMaps.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GMSServices provideAPIKey:@"YOUR KEY HERE"];
[GeneratedPluginRegistrant registerWithRegistry:self];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end

最新更新