【问题标题】:Correct way of storing API Keys in flutter following best practises遵循最佳实践在颤振中存储 API 密钥的正确方法
【发布时间】:2019-01-24 11:38:17
【问题描述】:

如果我想在 github 上推送代码,在颤振中添加秘密 API 密钥的正确方法是(最佳实践)。我制作了一个使用 API 的简单应用程序,但我以粗鲁的方式使用密钥只是为了测试应用程序是否正常工作。通常根据我在后端开发应用程序的经验,密钥存储在某个地方和不同的文件中,然后只需将其导入到需要API_KEY 的所需文件中,并排除.gitignore 文件中的文件。

到目前为止,我也实现了这种方法:

文件夹树

-lib
  -auth
    -keys.dart
    -secrets.json 

secrets.json

我将在此处添加KEY 并在.gitignore 中指定此文件,以便在我推送代码时将其排除在github 中。

//Add API KEY HERE
{
  "api_key": "ee4444444a095fc613c5189b2"
}

keys.dart

import 'dart:async' show Future;
import 'dart:convert' show json;
import 'package:flutter/services.dart' show rootBundle;


class Secret {
  final String apikey;

  Secret({this.apikey=""});

  factory Secret.fromJson(Map<String, dynamic>jsonMap){
    return new Secret(apikey:jsonMap["api_key"]);
  }
}


class SecretLoader {
  final String secretPath;

  SecretLoader({this.secretPath});
  Future<Secret> load() {
    return rootBundle.loadStructuredData<Secret>(this.secretPath,
            (jsonStr) async {
          final secret = Secret.fromJson(json.decode(jsonStr));
          return secret;

        });
  }
}

我觉得这种方法太过分了。我想得到更好的方法的建议。

【问题讨论】:

  • 如果不应该共享;理想情况下,它不应该在客户端上。最终,一旦您发布了您的应用程序,人们就可以对其进行反编译以获取其中的所有内容。
  • 我使用的 API 要求我添加密钥,以便获得所需的有效负载。该应用程序正在使用 API,并且需要添加密钥才能访问有效负载。我可以将密钥存储在哪里,以便在需要时访问它们?
  • 我喜欢这种做事方式。我在我的应用程序中做了非常相似的事情。我还将创建一个main_dev.dartmain_prod.dart——每个文件都将针对运行该版本的应用程序。在每个文件中,我将导入相应的secrets.json 并在整个应用程序中使用它。
  • 您实际上是如何在代码中检索 api 密钥字符串的?
  • 如果你依赖带有秘密的 gitignored 文件,只需使用 static const 键创建一个 dart 文件。更容易使用

标签: dart flutter


【解决方案1】:

编辑:看看下面 J. Saw 的评论。

编辑 2:底部描述的问题已在 firebase-config 19.0.2 中修复。

使用 Firebase Remote Config 在 Firebase 控制台的菜单中,向下滚动到 Grow,然后滚动到 Remote Config。在这里您可以添加一个带值的参数。完成后不要忘记发布更改。这有点微妙。

现在为 Flutter 安装 firebase_remote_config

导入所有内容后,您可以使用以下代码检索您的值:

RemoteConfig remoteConfig = await RemoteConfig.instance;
await remoteConfig.fetch(expiration: Duration(hours: 1));
await remoteConfig.activateFetched();

remoteConfig.getValue('key').asString();

这样,API 密钥或令牌永远不会成为您应用程序的一部分。

注意:目前有一个issue,您会在其中收到一条警告,指出未设置应用程序的名称,但这不会影响功能。

【讨论】:

  • 我喜欢这个策略。但是,您有像 pub.dev/packages/google_maps_flutter#getting-started 这样的文档,它告诉人们将 API KEY 放在 AndroidManifest.xmlAppDelegate.m 中。这不是坏习惯吗?应该如何取代这一策略?
  • Per Firebase:“不要将机密数据存储在远程配置参数键或参数值中。可以对存储在项目的远程配置设置中的任何参数键或值进行解码。” (firebase.google.com/docs/remote-config)
  • 关于如何做到这一点的任何建议。您认为 firebase realtime/datastore 是更好的选择吗?
【解决方案2】:

对于安全存储,您必须依赖相应的原生平台,iO 和 Android 都提供了一种安全存储密钥的机制。您可以自己实现它,并使用颤振通道来获取和存储密钥。可以在此处阅读有关此机制的信息:

Android Keystore

iOs KeyChain

另外,你可以使用thisflutter插件,它使用上面提到的服务并提供一个dart对象来访问安全存储。

【讨论】:

  • 这无济于事,因为您有时会将 API 机密放入代码中,而反编译 APK 仍会泄露机密!!!
【解决方案3】:

如前所述,如果密钥是秘密并且您想保护它,那么就不要将它放在客户端应用程序中。该应用程序可以反编译,并且可以为愿意针对您的客户的人提取密钥。

我会将与此 API 通信的任务委托给您的应用程序服务器。您可以将密钥放在您的服务器中,让您的服务器与此外部 API 进行通信,并将响应转发给客户端。

编辑:另一种不太安全但更方便的方法是使用 proguard 之类的东西来混淆你的代码。有关 android 应用程序的颤振说明请参见此页面:https://flutter.io/android-release/

【讨论】:

  • 我不想为此花费额外的时间来构建后端服务器,我进行了研究并发现了 android 在使用 java 构建它时如何处理它:(stackoverflow.com/questions/14570989/…)。必须有办法让颤振处理这个问题。也在这里github.com/codepath/android_guides/wiki/…
  • 但是,如果您从自己的服务器请求 API,如果他们知道可以再次从您的代码中检索到的 URI,每个人都可以这样做。
【解决方案4】:

你可以使用官方 Flutter Packages 中的flutter_secure_storage

【讨论】:

  • 可能是一个愚蠢的问题,但是在使用这个包时,我仍然依赖于将密钥放在我的源代码中,因为它们最终必须在某个时候添加到安全存储中,所以我可以稍后阅读。还是我在这里误解了什么?
  • 我认为你理解正确。如果您从 用户 那里获得秘密并希望安全地存储它们,该软件包会有所帮助。
猜你喜欢
  • 2011-09-23
  • 2022-11-03
  • 1970-01-01
  • 2014-07-28
  • 2021-09-18
  • 2019-07-30
  • 1970-01-01
  • 2010-11-18
  • 2021-08-05
相关资源
最近更新 更多