Как добавить CAPTCHA в приложения для Android
() translation by (you can also view the original English article)
Если вы разрабатываете приложение для Android, которое должно взаимодействовать с вашим внутренним сервером, важно принять меры для его защиты от автоматизированных скриптовых ботов, которые пытаются выдавать себя для человека. В противном случае ваш сервер может быть ими атакован.
CAPTCHA, сокращение от Completely Automated Public Turing tests for telling Computers and Humans Apart, в настоящее время является наиболее эффективной защитой от ботов. Как вы, возможно, уже знаете, они обычно представляют собой образ, голос или тесты на основе здравого смысла, которые легко доступны для людей, но чрезвычайно сложны для компьютеров.
В этом уроке я покажу вам, как использовать недавно выпущенный API reCAPTCHA для добавления CAPTCHA в ваши приложения для Android.
Предпосылки
Чтобы иметь возможность следовать этой статье, вам понадобится следующее:
- Android Studio 3.0 Canary 4 или выше
- устройство или эмулятор под управлением Android 4.4 или выше
- Node.js 8.1.3 или выше
1. Настройка проекта
Запустите Android Studio и создайте новый проект с пустым действием. В настройке нового проекта убедитесь, что вы вводите осмысленное имя пакета - вы будете использовать его при регистрации своего приложения с помощью службы reCAPTCHA.
Кроме того, установите флажок Включить поддержку Kotlin. Поскольку Kotlin теперь является официальным языком Android, в этом учебнике мы будем использовать его вместо Java.



API SafetyNet входят в состав сервисов Google Play. Чтобы иметь возможность использовать их в своем проекте, добавьте следующую implementation
зависимость в файл build.gradle модуля app
:
1 |
implementation 'com.google.android.gms:play-services-safetynet:11.0.2' |
Кроме того, для выполнения сетевых операций мы будем использовать библиотеку Fuel, которая имеет очень сжатый API на основе Kotlin. Поэтому добавьте его как другую implementation
зависимость.
1 |
implementation 'com.github.kittinunf.fuel:fuel-android:1.8.0' |
Вы не можете выполнять сетевые операции без разрешения INTERNET
, поэтому добавьте следующую строку в файл манифеста вашего проекта:
1 |
<uses-permission android:name="android.permission.INTERNET"/> |
Наконец, нажмите кнопку Синхронизировать сейчас, чтобы завершить настройку проекта.
2. Получение ключей reCAPTCHA
Перед использованием службы reCAPTCHA вам понадобятся два ключа:
- ключ сайта, который должен быть передан службе из вашего приложения для Android
- и секретный ключ, который должен быть передан службе с вашего внутреннего сервера
Чтобы получить ключи, используйте свою учетную запись Google и войдите в консоль администратора reCAPTCHA. Если вы впервые открываете консоль, вам автоматически будет представлена краткая форма регистрации, в которой вы можете ввести имя своего приложения.



После того, как вы примете условия обслуживания reCAPTCHA, нажмите кнопку Зарегистрироваться, чтобы сгенерировать оба ключа.
.png)
.png)
.png)
Теперь вы можете добавить ключ сайта в свой проект Android Studio, просто указав его внутри файла res/values/strings.xml:
1 |
<string name="my_site_key">ABCDEFGHIJKLMNOPQ1234567890</string> |
Мы будем работать с секретным ключом только в конце этого урока, поэтому запишите его сейчас в безопасное место.
3. Создание CAPTCHA
Когда мы слышим слово CAPTCHA, мы обычно думаем о грязных изображениях, содержащих трудночитаемые буквы и цифры. Однако такие CAPTCHA, благодаря достижениям в области технологий компьютерного зрения, уже недостаточно хороши, чтобы остановить всех ботов.
CAPTCHA, созданные службой reCAPTCHA, очень продвинуты и очень интерактивны. Фактически, их решение сродни игре в простые игры. Следовательно, вы не можете напрямую вставлять их в макет своей деятельности. Вместо этого вы должны добавить кнопку в макет, при нажатии на которую пользователь должен увидеть новый экран или диалоговое окно, содержащее CAPTCHA.
В следующем коде показано, как добавить виджет Button
в XML-файл макета вашей деятельности:
1 |
<Button
|
2 |
android:id="@+id/are_you_human_button" |
3 |
android:layout_width="wrap_content" |
4 |
android:layout_height="wrap_content" |
5 |
android:layout_centerHorizontal="true" |
6 |
android:layout_centerVertical="true" |
7 |
android:text="Are you human?" /> |
Прежде чем вы начнете генерировать CAPTCHA, вам придется инициализировать клиент для API SafetyNet. Вы можете сделать это, вызвав метод getClient()
класса SafetyNet
. Соответственно, добавьте следующий код внутри метода onCreate()
вашего класса Activity
:
1 |
val myClient: SafetyNetClient = SafetyNet.getClient(this) |
CAPTCHA должна отображаться, когда пользователь нажимает кнопку, поэтому добавьте обработчик события on-click к нему, используя метод setOnClickListener()
. Внутри обработчика все, что вам нужно сделать, это вызвать метод verifyWithRecaptcha()
и передать ключ вашего сайта в качестве аргумента, чтобы открыть диалог, содержащий CAPTCHA.
Возвращаемое значение метода verifyWithRecaptcha()
является объектом Task
. Присоединив к нему обработчик события on-success, вы сможете получить объект RecaptchaTokenResponse
, содержащий токен, который вы можете использовать, чтобы указать, прошел ли пользователь или не прошел CAPTCHA:
1 |
are_you_human_button.setOnClickListener { |
2 |
myClient
|
3 |
.verifyWithRecaptcha(resources.getString(R.string.my_site_key)) |
4 |
.addOnSuccessListener { successEvent -> |
5 |
val token: String = successEvent.tokenResult |
6 |
|
7 |
// More code here
|
8 |
}
|
9 |
}
|
4. Проверка токенов CAPTCHA
Токен, полученный на предыдущем шаге, должен снова быть передан службе reCAPTCHA, чтобы проверить, прошел ли пользователь или не прошел тест. Однако на этот раз вызов службы reCAPTCHA должен быть сделан с вашего внутреннего сервера.
Разумеется, сервер не будет иметь токен, если ваше приложение Android не отправит его ему. Поэтому теперь мы должны написать код для отправки токенов из приложения Android на сервер.
Пока давайте предположим, что наш сервер имеет конечную точку под названием validate
, которая может принимать токен в качестве параметра строки запроса. Я буду использовать 10.0.2.2 в качестве IP-адреса сервера и 8000 в качестве порта. Если вы собираетесь запускать сервер на своем компьютере и в приложении на эмуляторе, запущенном на том же компьютере, вы также можете использовать один и тот же IP-адрес.
1 |
val serverURL: String = "https://10.0.2.2:8000/validate" |
Теперь вы можете вызвать метод httpGet()
библиотеки Fuel
, чтобы отправить токен на сервер. Метод ожидает, что список параметров строки запроса будет единственным аргументом, поэтому я предлагаю вам использовать метод утилиты listOf()
для создания списка, содержащего один элемент: токен, назначенный параметру запроса с именем user_token.
Поскольку метод httpGet()
выполняется асинхронно, вы должны вызвать метод responseString()
для обработки возвращаемого значения. В следующем коде показано, как это сделать:
1 |
serverURL.httpGet(listOf("user_token" to token)) |
2 |
.responseString { request, response, result -> |
3 |
// More code here
|
4 |
}
|
Вы можете видеть, что теперь у нас есть доступ к объекту result
. В случае отсутствия ошибок он будет содержать ответ нашего сервера в виде строки.
Предположим, что наш сервер возвращает строку «PASS», если пользователь проходит тест, и «FAIL» в противном случае. То, что вы на самом деле делаете, когда пользователь проходит или не проходит тест, конечно, зависит от вас. Пока я предлагаю вам просто отображать соответствующие сообщения Toast
. Следующий код показывает вам, как сделать это кратко:
1 |
result.fold({ data -> |
2 |
if(data.contains("PASS")) |
3 |
Toast.makeText(baseContext, |
4 |
"You seem to be a human.", |
5 |
Toast.LENGTH_LONG).show() |
6 |
else
|
7 |
Toast.makeText(baseContext, |
8 |
"You seem to be a bot!", |
9 |
Toast.LENGTH_LONG).show() |
10 |
}, { error -> |
11 |
Log.d("ERROR", "Error connecting to the server") |
12 |
})
|
На данный момент приложение готово. Вы можете продолжить и развернуть его на свой эмулятор или устройство.



5. Создание сервера
Мы уже сделали несколько предположений о нашем веб-сервере на более ранних этапах. Настало время создать его, убедившись, что он не отклоняется от этих предположений.
Быстрый и простой способ создания полностью функционального веб-сервера - использовать платформу Node.js и фреймворк Express.js. Чтобы создать новый проект Node.js, создайте новый каталог на своем компьютере и запустите в нем команду npm init
.
1 |
mkdir my_web_server
|
2 |
cd my_web_server ; npm init -y |
Чтобы добавить фреймворк Express к проекту, вы можете использовать команду npm install
.
1 |
npm install --save express |
Кроме того, нам понадобится пакет Request для связи с сервисом reCAPTCHA. Поэтому установите его как зависимость.
1 |
npm install --save request |
Теперь вы можете использовать свой любимый редактор кода для создания нового файла с именем index.js и начать писать необходимый код на стороне сервера.
Начните с загрузки модулей express
и request
с помощью функции require()
и создания нового Express-приложения, вызвав функцию express()
.
1 |
const express = require('express'); |
2 |
const request = require('request'); |
3 |
|
4 |
const myApp = express(); |
У нашего экспресс-приложения должна быть конечная точка, называемая validate
, к которой можно получить доступ, используя метод HTTP GET. Поэтому создайте для него новый маршрут, используя метод get()
:
1 |
myApp.get('/validate', function(req, resp) { |
2 |
// More code here
|
3 |
});
|
Чтобы проверить токен, созданный приложением Android, вы должны теперь сделать запрос POST службе reCAPTCHA. Запрос должен содержать ваш секретный ключ и сам токен. В следующем коде показано, как создать тело запроса POST, извлекая токен из строки запроса:
1 |
const postData = { |
2 |
secret: '1234567890-abcdefghijklmnopqr', |
3 |
response: req.query.user_token |
4 |
};
|
Чтобы действительно выполнить запрос POST, вы можете вызвать метод post()
модуля request
. Его ответ - это короткий документ JSON, содержащий ключ success
. Как и следовало ожидать, его значение будет true
, только если пользователь прошел проверку
Следующий код показывает вам, как разбирать документ JSON, извлекать ключ success
и генерировать ответы «PASS» и «FAIL», которые требуется нашим приложениям для Android:
1 |
request.post({ |
2 |
url: 'https://www.google.com/recaptcha/api/siteverify', |
3 |
form: postData |
4 |
}, function(error, response, body) { |
5 |
jsonData = JSON.parse(body); // Parse the JSON document |
6 |
|
7 |
if(jsonData.success) { // User passed the test |
8 |
resp.send('PASS'); |
9 |
} else { // User didn't pass the test |
10 |
resp.send('FAIL'); |
11 |
}
|
12 |
|
13 |
});
|
Наконец, вы должны вызвать метод listen()
объекта приложения Express, чтобы он мог прослушивать соединения.
1 |
myApp.listen(8000); |
На этом этапе наш веб-сервер готов. Чтобы запустить его, вернитесь к терминалу и выполните следующую команду:
1 |
node index.js |
Если вы запустите приложение Android сейчас, нажмите кнопку и успешно разрешите CAPTCHA, вы увидите сообщение Toast
, сообщающее вам, что вы человек.



Заключение
Теперь вы знаете, как использовать API-интерфейс SafetyNet reCAPTCHA для защиты вашего приложения Android и внутренней инфраструктуры от ботов. Вам больше не нужно беспокоиться об автоматизированных регистрациях, скриншотах экрана или спаме, созданных ботом.
Чтобы узнать больше о API reCAPTCHA, вы можете обратиться к официальной документации.
Тем временем, ознакомьтесь с некоторыми из наших замечательных статей о разработке приложений для Android!