我的服务器如何安全地验证iPhone应用内购买?

时间:2009-10-17 02:35:52

标签: iphone authentication iphone-sdk-3.0 certificate in-app-purchase

查看Apple的server purchase model图表。

在第9步中,服务器怎么知道它真的在与有权购买的iPhone交谈,而且Eve没有用不诚实获得的收据进行重播?

收据可能有效,但这并不能证明发件人是有资格的一方。

iPhone上是否有可用于签署收据的设备证书?

有没有办法将收据绑定到设备,或将收据绑定到iTunes帐户和设备,以便服务器可以验证?

4 个答案:

答案 0 :(得分:33)

Apple提供的易受攻击的方法

服务器可以doing the following验证购买:

  1. iPhone应用程序在购买后收到transactionReceipt。让iPhone base64对其进行编码(您可以使用此开源addition to NSData并将其发送到您的服务器。 (您甚至可以按原样发送它,并让服务器base64在验证之前对其进行编码。)

  2. 让您的服务器使用HTTP POST将带有base64编码transactionReceipt的单个密钥receipt-data发送到https://buy.itunes.apple.com/verifyReceipt的JSON请求。 (有关如何使用各种服务器端语言执行此操作的说明see this site

  3. 服务器将使用带有两个密钥的JSON对象进行响应:status这是一个整数,receipt是重复的收据。

  4. 如果状态为零,则应接受收据有效,非零值表示收据无效。

    安全加入Apple的方法

    但是,存在一些安全隐患。用户可以使用其他用户的收据,因为设备不与收据绑定,或者用户可以使用其他产品的收据,因为服务器不验证收据的产品ID。为确保不会发生这种情况,您还应执行以下操作:

    1. 当您第一次收到应用程序中的收据时,立即通过安全通道(如HTTPS或SSL套接字)将其与device's UUID一起发送到您的服务器。 不要将其存放在任何地方,请将其留在内存中。

    2. 在您的服务器上,将UUID和收据对存储在数据库中。

    3. 当设备发送UUID和收据对时,请向您的数据库确认收据尚未使用,通过检查{确保收据实际上是您的产品的收据{3}}。 收据只是一个JSON对象,因此您的服务器可以通过解码来自base64的收据来读取内容。

    4. 通过安全通道向设备返回响应,告知其购买是否为:

      • 以新身份验证(不在数据库中且有效)
      • 过去进行过身份验证(相同的UUID和收据对已在DB中)
      • 由于错误的产品ID而被拒绝
      • 由于已将收据与另一个UUID一起使用而被拒绝。
    5. 由于收据仅存储在设备的内存中,并且您的应用程序使用设备的UUID(可以是receipt's product id ,请参阅评论),并记录所有购买的产品以安全的方式在服务器上使用设备的UUID;用户无法使用其他用户的收据验证购买,也无法使用其他产品的收据,因为您检查了该收据。

      如果要验证交易的其他详细信息,还可以验证收据中的其他字段。例如,如果您的产品是订阅,那么您也希望查看交易日期。

      此外,用户不能伪装成您的服务器,因为他们没有您的SSL证书,因此将设备置于具有与您相同名称的主机的专用网络上。

      失败注意事项

      由于在用户的设备收到收据并使用您的服务器进行验证之间可能会发生故障(例如,如果用户失去连接,或者您的服务器因维护而关闭),您也应该让用户“重新授权” 。重新授权应该从商店(使用spoofed by jailbroken devices获取收​​据,然后将其重新发送到服务器,就像这是一次新购买一样。这应该很少需要使用,但应该可以保存用户在网络出现故障时不得不重新购买产品。

      考虑多个设备

      这意味着如果用户想要在多个设备上使用应用程序,他们将不得不多次购买该产品。这可能是期望的效果,但您可能应该在购买之前通知用户,因为他们可能希望能够使用与其帐户关联的设备中的内容。

      如果收据还包含iTunes帐户信息,则身份验证可以使用该信息允许用户在其所有设备(但不是他们的朋友)之间共享内容。

答案 1 :(得分:0)

我认为不能将收据绑定到设备上。

我的理解是,您可以在多个设备上安装应用程序而无需额外费用。将其绑定到设备意味着如果您升级/更换手机,则需要再次购买所有应用。

答案 2 :(得分:0)

我相信如果您无法读取用户的苹果ID,那么您对盗版的唯一保护就是跟踪(当然是服务器端)每个transaction_id的下载请求数量,并限制他们超过一定的价值。

因此,如果您将其限制为50,那么为用户在多台设备上部署应用程序及其内容提供了合理的余地并且可以多次恢复,但是对于想要分发盗版者的人来说却很难带有效回执的版本,用于无限制恢复。当然,他们只能发布包含您所有内容的版本,但您无法做到这一点,至少他们不会对您的服务器征税。

答案 3 :(得分:0)

UDID不再起作用

Beniot的答案很棒,但是,正如Joe D'Andrea所提到的,UDID已被弃用,我最后一次尝试时,使用该调用获取UDID的应用程序在上传到iTunes时无法通过验证。

作为收据计数器替代的限时收据

要添加到hloupyhonza的答案,除了为特定收据设置“下载请求”计数器外,您还可以按时间限制收据有效性。我找到了12到24小时之间合理的东西。

此方法还允许购买者在他拥有的任何其他设备上使用购买,只要他使用相同的Apple ID登录App Store即可。注意:每次完成恢复购买时,Apple都会返回一个全新的收据(包含原始收据的详细信息) - 这样可以使购买恢复超过我们为特定收据设置的时间限制。

防止“现成”黑客

为了防止典型的“Google搜索”黑客攻击解决方案(我的数据显示这构成了几乎所有的IAP黑客攻击尝试),我使用校验和(选择您喜欢的算法,无论如何,除非您想让它保持水密)以下级联:

  • receipt-data json string
  • 共享密钥
  • 验证成功状态代码。

应用程序将验证验证服务器返回的校验和。这不是防水的,因为黑客可能会从你的应用程序的二进制文件中检索共享密钥。但它已经阻止了迄今为止所有“现成的”黑客攻击,这对我的使用已经足够了。