blob: 4aff17d46f6f514022aa570839b4570e55050414 [file] [log] [blame]
page.title=安全性和设计
parent.title=In-app Billing
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>本文内容</h2>
<ol>
<li><a href="#billing-security">安全性方面的最佳做法</a>
<ol>
<li><a href="#unlocked">保护未锁定的内容</a></li>
<li><a href="#obfuscate">混淆你的代码</a></li>
<li><a href="#sample">修改示例代码</a></li>
<li><a href="#nonce">使用安全随机数</a></li>
<li><a href="#payload">设置开发者有效内容字符串</a></li>
<li><a href="#trademark">报告商标和版权侵权</a></li>
<li><a href="#revocable">实施可撤消的方案</a></li>
<li><a href="#key">保护你的公钥</a></li>
</ol>
</li>
</ol>
<h2>另请参见</h2>
<ol>
<li><a href="{@docRoot}google/play/billing/billing_overview.html">应用内结算概述</a></li>
</ol>
</div>
</div>
<p>在设计应用内结算的实施时,请务必遵循本文中介绍的安全性和设计指南。这些指南是推荐的最佳做法,适用于所有使用 Google Play 应用内结算服务的开发者。</p>
<h2>安全性方面的最佳做法</h2>
<h3 id="sign">在服务器上执行签名验证任务</h3>
<p>如果可能的话,你应该在远程服务器上(而不是设备上)执行签名验证。在服务器上实施验证过程,可有效防止攻击者通过对 .apk 文件进行反向工程来破坏验证过程。如果你将安全性流程放置到远程服务器上,请确保设备服务器的握手过程是安全的。</p>
<h3 id="unlocked">保护你的未锁定内容</h3>
<p>为防止恶意用户重新分发你未锁定的内容,请不要将这种内容放入你的 .apk 文件中,而是执行以下操作之一:</p>
<ul>
<li>使用实时服务发送内容,例如内容 Feed。通过实时服务发送内容可保持内容始终是最新的。</li>
<li>使用远程服务器发送内容。</li>
</ul>
<p>当你通过远程服务器或实时服务发送内容时,你可以将未锁定内容存储在设备内存中或设备的 SD 卡上。如果你将内容存储在 SD 卡上,请务必将内容加密并使用设备专有的密钥。</p>
<h3 id="obfuscate">混淆你的代码</h3>
<p>你应混淆应用内结算代码,让攻击者难以对你的安全协议和其他应用组件进行反向工程。我们建议你至少对代码运行 <a href="{@docRoot}tools/help/proguard.html">Proguard</a> 等代码混淆工具。</p>
<p>除了运行代码混淆程序以外,我们还建议你使用以下技术混淆你的应用内结算代码。</p>
<ul>
<li>将方法内嵌入其他方法中。</li>
<li>创建动态字符串,而不是将其定义为常量。</li>
<li>使用 Java 反射来调用方法。</li>
</ul>
<p>使用这些技术有助于缩小你应用的受攻击范围,并最大程度帮助你抵御会对应用内结算实施造成损害的攻击。</p>
<div class="note">
<p><strong>注意</strong>:如果你使用 Proguard 来对代码进行混淆处理,则必须将以下内容行添加到 Proguard 配置文件中:</p>
<p><code>-keep class com.android.vending.billing.**</code></p>
</div>
<h3 id="sample">修改所有示例应用代码</h3>
<p>应用内结算示例是可供任何人下载的公开发布应用。这意味着如果你直接使用发布的示例代码,则对攻击者而言比较容易对你的应用进行反向工程。请紧记示例应用只能作为示例使用。如果你使用示例应用中的任何一部分,则必须在发布之前或将其作为生产应用的一部分前对其进行修改。</p>
<p>尤其要注意的是,攻击者会寻找应用内已知的进入点和离开点,因此请务必修改与示例应用完全相同的代码部分。</p>
<h3 id="nonce">使用安全随机数</h3>
<p>随机数必须是不可预测的,也不能重复使用。在生成随机数时,请务必使用采用加密保护的随机数字生成器(例如 <code><a href="{@docRoot}reference/java/security/SecureRandom.html">SecureRandom</a></code>),这样可以减少重放攻击。</p>
<p>此外,如果你在服务器上执行随机数验证,请务必在服务器上生成随机数。</p>
<h3 id="payload">在提交购买请求时设置开发者有效内容字符串</h3>
<p>使用应用内结算 API 3 版,你可以在向 Google Play 发送购买请求时包括一个“开发者有效内容”字符串令牌。通常情况下,这样做是为了提交可唯一标识此购买请求的字符串令牌。如果你指定字符串值,那么 Google Play 会返回购买响应以及该字符串。随后,在你针对此购买进行查询时,Google Play 会返回此字符串以及购买详情。</p>
<p>提交字符串令牌可以帮助应用识别进行了购买的用户,以便你稍后验证该用户进行的购买是否合法。对于消耗型商品,你可以使用随机生成的字符串;但是对于非消耗型商品,则应该使用可唯一标识用户的字符串。</p>
<p>当你获得 Google Play 的响应时,请确保开发者有效内容字符串匹配你之前与购买请求一起发送的令牌。作为进一步的安全预防措施,你应该在自己的安全服务器上执行验证。</p>
<h3 id="trademark">针对商标和版权侵权采取行动</h3>
<p>如果你看到自己的内容在 Google Play 上被重新分发,请立即、果断地采取行动。发出<a href="http://support.google.com/googleplay/android-developer/bin/answer.py?hl=zh-CN&amp;answer=141511">商标侵权通知</a>或<a href="http://www.google.com/android_dmca.html">版权侵权通知</a>。</p>
<h3 id="revocable">针对未锁定内容实施可撤消方案</h3>
<p>如果你使用远程服务器发送或管理内容,请确保当用户访问内容时,应用能够验证未锁定内容的购买状态。这样你可以根据需要撤消使用,并最大限度地减少盗版。</p>
<h3 id="key">保护你的 Google Play 公钥</h3>
<p>为保护你的公钥安全并防止被恶意用户和黑客攻击,请不要将其作为文字字符串嵌入任何代码中。而是在运行时以拼凑方式构建字符串或者使用位操作处理(例如,XOR 搭配其他字符串)以隐藏真实密钥。公钥本身不是秘密信息,但是你一定不希望黑客或恶意用户能轻易将公钥替换为其他钥匙。</p>