【问题标题】:Google Cloud Translate API Key Doesn't Work When Using Android Application Restrictions使用 Android 应用程序限制时,Google Cloud Translate API 密钥不起作用
【发布时间】:2021-11-25 18:34:18
【问题描述】:

我正在尝试在我的 Android 应用中仅使用密钥作为身份验证来实现 Google Cloud 的翻译 API。我没有服务器或任何东西来提高安全性,所以我想通过指定应用程序包名称和 SHA-1 哈希来限制 API 密钥只能由我的 Android 应用程序使用。以下是我在 Cloud API & Services 页面中使用的设置:

为确保信息正确,我将 Gradle App ID 设置为指定的包名称:

我在 windows 中为 SHA-1 哈希运行了提供的 keytool 命令:

Gradle 的签名报告工具也返回相同的哈希值:

当我尝试调用支持语言的简单 GET 请求时,响应始终是 403 Forbidden 错误。 但是,当我取消对仅 Android 应用程序和包/哈希设置的限制时,密钥有效。我显然在这里做错了什么还是忘记了什么?当我什至记录 BuildConfig.getPackage() 时,它返回相同的包名称。获取 SHA-1 哈希的两种方法都返回相同的哈希。我不确定出了什么问题。

【问题讨论】:

  • 您在项目中启用了Google Translate API?您是否遵循任何文档来创建和使用 API?你用this docs了吗?你的问题和this Stack thread类似吗?

标签: android google-cloud-platform google-api google-oauth


【解决方案1】:

几天前终于弄明白了。仅从应用程序包发送 API 请求并不意味着它已在某处使用该信息进行编码,以便 API 端点知道它来自授权访问者。

请求需要两个头部属性来指定源包和签名,格式为:

{
    "X-Android-Package": "package.name.here",
    "X-Android-Cert": "debug:or:release:signature:here"
}

这在 Google 文档中是没有的。我不知道为什么,令人沮丧的是,当使用纯 REST 而不是 Google 的客户端库时,这显然是每个人都需要知道的。

这意味着将这些值硬编码并不是一个好主意,因为有人可以反编译 apk 并获得这些标头的授权访问者凭据。但是您可以通过使用几个可用的函数来获取此信息来使其变得更加困难。

获取包名很简单:

context.getPackageName()

签名需要一些工作

public String getSignature(Context context) {
    PackageInfo info = null;
    try {
        info = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNING_CERTIFICATES);
        Signature[] sigHistory = info.signingInfo.getSigningCertificateHistory();
        byte[] signature = sigHistory[0].toByteArray();
        MessageDigest md = MessageDigest.getInstance("SHA1");
        byte[] digest = md.digest(signature);
        StringBuilder sha1Builder = new StringBuilder();
        for (byte b : digest) sha1Builder.append(String.format("%02x", b));
        return sha1Builder.toString();
    } catch (PackageManager.NameNotFoundException | NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return null;
}

请务必阅读SigningInfo documentation 以正确使用它。

从那里设置请求标头。我一直在使用 Apache 的 Http Clients:

HttpGet getReq = new HttpGet(uri);
getReq.setHeader("X-Android-Package", context.getPackageName());
getReq.addHeader("X-Android-Cert", getSignature(context));

【讨论】:

    猜你喜欢
    • 2018-02-21
    • 2017-12-24
    • 1970-01-01
    • 1970-01-01
    • 2017-07-08
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 2018-06-14
    相关资源
    最近更新 更多