安全性和设计

在您设计应用内购买结算的实现时,请务必遵循本文档中介绍的安全性和设计准则。 这些准则是推荐的最佳做法,适用于使用 Google Play 应用内购买结算服务的所有开发者。

安全性最佳做法

在服务器上执行签名验证任务

如果可能,您应该在远程服务器(而不是设备)上执行签名验证。在服务器上实现验证过程可有效防止攻击者通过对 .apk 文件进行反向工程来破坏验证过程。 如果您将安全性流程放到远程服务器上,请确保设备到服务器的握手过程是安全的。

保护未锁定的内容

为了防止恶意用户重新分发您未锁定的内容,请不要将这种内容放到您的 .apk 文件中, 而是执行以下操作之一:

  • 使用实时服务发送内容,例如内容 Feed。通过实时服务发送内容可以使内容始终保持最新状态。
  • 使用远程服务器发送内容。

通过远程服务器或实时服务发送内容时,您可以将未锁定的内容存储在设备内存中或设备的 SD 卡上。 如果将内容存储在 SD 卡上,请务必将内容加密并使用设备特定的加密密钥。

混淆您的代码

您应混淆应用内购买结算代码,让攻击者难以对您的安全协议和其他应用组件进行反向工程。 我们建议您至少对代码运行 Proguard 等代码混淆工具。

除了运行代码混淆程序以外,我们还建议您使用以下技术混淆您的应用内购买结算代码。

  • 将方法内嵌入其他方法中。
  • 创建动态字符串,而不是将其定义为常量。
  • 使用 Java 反射来调用方法。

使用这些技术有助于缩小应用的受攻击范围,并最大程度帮助您抵御会对应用内购买结算实现造成损害的攻击。

:如果您使用 Proguard 对代码进行混淆处理,则必须将以下内容行添加到 Proguard 配置文件中:

-keep class com.android.vending.billing.**

修改所有示例应用代码

应用内购买结算示例应用是可供任何人下载的公开分发应用。这意味着如果您直接使用发布的示例代码,则对攻击者而言,对您的应用进行反向工程就比较容易。 示例应用只能作为示例使用。 如果您使用示例应用的任何部分,则必须在发布之前或将其作为生产应用的一部分前对其进行修改。

尤其需要注意的是,攻击者会寻找应用内已知的进入点和离开点,因此请务必修改与示例应用完全相同的代码部分。

使用安全的随机数

随机数必须是不可预测的,也不能重复使用。在生成随机数时,请务必使用采用加密保护的随机数字生成器(例如 SecureRandom)。 这样可以减少重放攻击。

此外,如果您在服务器上执行随机数验证,请务必在服务器上生成随机数。

在提交购买请求时设置开发者有效负载字符串

使用 In-app Billing Version 3 API,您可以在向 Google Play 发送购买请求时包括一个“开发者有效负载”字符串令牌。 通常情况下,这样做是为了传递可唯一标识此购买请求的字符串令牌。如果您指定字符串值,Google Play 会返回此字符串以及购买响应。 随后,在您针对此购买进行查询时,Google Play 会返回此字符串以及购买详情。

传递的字符串令牌应帮助应用识别已进行购买的用户,以便您稍后验证该用户进行的购买是否合法。 对于消耗型商品,您可以使用随机生成的字符串;但是对于非消耗型商品,则应该使用可唯一标识用户的字符串。

:请勿在有效负载字符串中使用用户的电子邮件地址,因为该地址可能会发生变化。

当您获得 Google Play 的响应时,请确保验证开发者有效负载字符串与您之前随购买请求一起发送的令牌匹配。 作为进一步的安全预防措施,您应该在自己的安全服务器上执行验证。

针对商标和版权侵权采取行动

如果您看到自己的内容在 Google Play 上被重新分发,请立即、果断地采取行动。发出商标侵权通知版权侵权通知

针对未锁定的内容实现可撤销的方案

如果您使用远程服务器发送或管理内容,请确保当用户访问内容时,应用能够验证未锁定内容的购买状态。 这样您可以根据需要撤销使用,并最大限度地减少盗版。

保护您的 Google Play 公钥

为了保护您的公钥安全并防止被恶意用户和黑客攻击,请不要将其作为文字字符串嵌入任何代码中。 而是在运行时以拼凑方式构建字符串或者使用位操作处理(例如,XOR 搭配其他字符串)以隐藏真实密钥。 公钥本身不是秘密信息,但是您一定不希望黑客或恶意用户能轻易将公钥替换为其他密钥。