Chinese (Simplified) (中文(简体)) translation by Zhang Xiang Liang (you can also view the original English article)
如果你正在开发需要与后端服务器进行交互的Android APP,那么你必须采取措施来与bots对抗,bots是自动化的脚本,这种脚本尝试假扮人类以通过验证。否则的话,你的服务器可能因频繁过度访问而崩溃。
CAPTCHAs(Completely Automated Public Turing tests for telling Computers and Humans Apart的简写)目前是防御bots的最有效方式。你可能已经知道,它们通常是对人类很容易的图像,语音或常识测试,但这种测试对计算机却非常困难。
在本教程中,我将展示如何使用新发布的SafetyNet reCAPTCHA API将CAPTCHAs添加到你的Android APP。
准备工作
为了保持与本文的一致,你需要下列内容:
- Android Studio 3.0 Canary 4或更高版本
- 运行Android 4.4或更高版本的设备或模拟器
- Node.js 8.1.3或更高版本
1.项目设置
启动Android Studio并创建带有空activity的新项目。在配置新的项目的表单中,确保输入有意义的包名称 - 因为这个包名会在使用reCAPTCHA服务注册APP时使用。
另外,勾选Include Kotlin Support。因为Kotlin现在是Android官方语言,所以我们将在本教程中使用它而不是Java。

SafetyNet API是Google Play服务的一部分。要在项目中使用它们,请将以下implementation
依赖项添加到app
module级的build.gradle文件中:
implementation 'com.google.android.gms:play-services-safetynet:11.0.2'
另外,我们将使用Fuel库来执行与网络相关的操作,该库具有非常简洁的基于Kotlin的API。因此,将其添加为另一个 implementation
依赖项。
implementation 'com.github.kittinunf.fuel:fuel-android:1.8.0'
因为有网络相关的操作,我们需要添加INTERNET
权限,因此请将以下行添加到项目的清单文件中:
<uses-permission android:name="android.permission.INTERNET"/>
最后,点击“ 立即同步” 按钮完成项目配置。
2.获取reCAPTCHA键
你需要两个密钥才能使用reCAPTCHA服务:
- 一个网站密钥,必须从你Android APP传递给该服务
- 一个秘密密钥,必须从后端服务器传递给服务
要获取密钥,请使用你的Google帐户登录到reCAPTCHA管理控制台。如果你是第一次打开控制台,则会自动显示一个简短的注册表单,您可以在其中输入应用的包名称。

你接受reCAPTCHA服务条款后,请继续按“ 注册”按钮生成两个密钥。
.png)
将网站密钥添加到res/values/strings.xml文件,即将网站密钥添加到Android Studio项目中。
<string name="my_site_key">ABCDEFGHIJKLMNOPQ1234567890</string>
我们将在本教程结尾处使用秘密密钥,所以你需要把秘密密钥放在安全的地方。
3.生成CAPTCHAs
当我们听到CAPTCHA这个词时,我们通常会想到难以读取的字母和数字。然而,由于计算机视觉技术的进步,这样的CAPTCHAs已经无法阻止所有bots了。
由reCAPTCHA服务产生的CAPTCHA是非常先进和可交互的。事实上,通过它们的验证类似于玩简单的游戏。 因此,你无法直接将其添加到activity的布局文件中。你必须在布局中添加一个按钮,当按下该按钮时,应该将用户引导到包含CAPTCHA的新界面或对话框。
以下代码显示了如何向XML布局文件中添加Button
控件:
<Button android:id="@+id/are_you_human_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="Are you human?" />
在开始生成CAPTCHAs之前,你必须初始化SafetyNet API的客户端。 你可以调用SafetyNet
类的getClient()
方法来实现。在Activity
类的onCreate
()方法中添加以下代码:
val myClient: SafetyNetClient = SafetyNet.getClient(this)
当用户按下按钮时,CAPTCHA必须显示,所以使用setOnClickListener
()方法添加一个点击事件来处理。在处理程序中,你需要做的就是调用verifyWithRecaptcha
()方法,并将网站密钥作为参数传递给它,以便打开包含人机验证码的对话框。
verifyWithRecaptcha
()方法返回一个Task
对象。 通过将一个成功的事件处理程序附加到它,你将获取一个包含令牌的RecaptchaTokenResponse
对象,你可以使用该对象来判断用户是否通过了CAPTCHA或失败了。过程如下:
are_you_human_button.setOnClickListener { myClient .verifyWithRecaptcha(resources.getString(R.string.my_site_key)) .addOnSuccessListener { successEvent -> val token: String = successEvent.tokenResult // More code here } }
4.验证CAPTCHA令牌
你在上一步中获得的令牌必须再次传递给reCAPTCHA服务,以检查用户是否通过或未通过测试。但是,这次必须由后端服务器调用reCAPTCHA服务。
服务器当然不会有令牌,除非你的Android APP发送给它了。因此,我们现在必须编写代码,将Android APP的令牌发送到服务器。
现在,假设我们的服务器有一个叫validate
的端点,它可以接受令牌作为查询字符串参数。我将使用10.0.2.2作为服务器的IP地址,8000作为端口。 如果你打算在自己的计算机上运行服务器,并在同一台计算机上运行的仿真器上运行该APP,那么也可以使用相同的IP地址。
val serverURL: String = "https://10.0.2.2:8000/validate"
你现在可以调用Fuel库提供的httpGet
()方法将令牌发送到服务器。该方法期望查询字符串参数列表作为其唯一参数,因此建议你使用listOf
()方法创建一个包含单个项目的列表,那单个项目为:分配给查询参数名为user_token
的令牌。
因为httpGet
()方法是异步运行的,你必须调用responseString
()方法才能处理其返回值。步骤如下:
serverURL.httpGet(listOf("user_token" to token)) .responseString { request, response, result -> // More code here }
你可以看到我们现在可以访问一个result
对象。如果没有错误,它将包含服务器响应的字符串。
如果用户通过测试,我们的服务器返回“PASS”字符串,否则返回“FAIL”字符串。当用户通过测试或失败时,你可以根据自己的需要做相应的处理。 现在,我建议你显示相应的Toast
消息。代码实现:
result.fold({ data -> if(data.contains("PASS")) Toast.makeText(baseContext, "You seem to be a human.", Toast.LENGTH_LONG).show() else Toast.makeText(baseContext, "You seem to be a bot!", Toast.LENGTH_LONG).show() }, { error -> Log.d("ERROR", "Error connecting to the server") })
现在,APP已经准备就绪。你可以运行了。

5.创建服务器
在较早的步骤中,我们对Web服务器做了很多假设。在前面那些假设的前提下,开始创建它吧。
快捷方便地创建功能齐全的Web服务器的方法是使用Node.js平台和Express.js框架。想要创建一个新的Node.js项目,先在计算机上创建一个新目录并运行npm init
。
mkdir my_web_server cd my_web_server ; npm init -y
要将Express框架添加到项目中,可以使用npm instal
l 命令。
npm install --save express
另外,我们需要Request包来与reCAPTCHA服务进行通信。因此,添加对Request包的依赖。
npm install --save request
你现在可以使用自己喜欢的代码编辑器来创建一个名为index.js的新文件, 并开始编写服务器端代码。
首先加载express
和request
模块,后者使用了require()
方法,然后通过调用express()
方法创建一个新的Express应用程序。
const express = require('express'); const request = require('request'); const myApp = express();
我们的Express应用程序必须具有一个叫validate
的端点,这个端点可以通过HTTP GET方法来访问。因此,使用get()
方法来创建新路由 :
myApp.get('/validate', function(req, resp) { // More code here });
要验证Android应用生成的令牌,你必须向reCAPTCHA服务发出POST请求。该请求必须包含你的密钥和令牌本身。 以下代码展示了通过从查询字符串中提取令牌来构建POST请求体:
const postData = { secret: '1234567890-abcdefghijklmnopqr', response: req.query.user_token };
要进行真正的POST请求,可以调用request
模块中post()
方法 。服务器响应是一个包含success
键的短JSON文档。机智如你,如果用户通过了测试,该success键的值才为true
。
以下代码显示了如何解析JSON文档,提取success
键,并生成Android APP需要的“PASS”和“FAIL”响应:
request.post({ url: 'https://www.google.com/recaptcha/api/siteverify', form: postData }, function(error, response, body) { jsonData = JSON.parse(body); // Parse the JSON document if(jsonData.success) { // User passed the test resp.send('PASS'); } else { // User didn't pass the test resp.send('FAIL'); } });
最后,你必须调用Express应用程序对象的listen()
方法来监听连接。
myApp.listen(8000);
现在我们的web服务器已经准备好了。开启服务器,在终端输入如下命令:
node index.js
如果你现在运行了Android APP,请点击按钮,并成功通过人机验证,然后你应该会看到一条Toast
消息,告诉你是人操作而不是机器操作的。

结语
你现在知道如何使用SafetyNet reCAPTCHA API来保护你的Android APP和后端基础设施免受bots攻击了。你再也不必担心自动注册,界面卡顿或bots产生的垃圾邮件了。
想了解有关reCAPTCHA API的更多信息,请参阅官方文档。
与此同时,请查看关于Android APP开发的其他文章!
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Update me weeklyEnvato Tuts+ tutorials are translated into other languages by our community members—you can be involved too!
Translate this post