本页介绍了如何在 iOS 应用中集成 Google Cloud Fraud Defense。
由于移动设备在屏幕尺寸、性能以及 应用界面方面存在差异,视觉复选框 reCAPTCHA 验证任务(我不是 机器人)不适用于 iOS 移动应用。您可以改为实现自己的分层强制执行策略,例如 MFA 流程,为可疑流量提供替代兑换路径。
该 SDK 利用反射和动态代码,以便在已部署的应用或 SDK 中更新和改进检测系统。 为避免干扰应用,系统中的可用类仅限于经过仔细控制的列表。
准备工作
将应用的最低 SDK 设置为 iOS 15 或创建新的移动应用。
创建 reCAPTCHA 密钥 为 iOS 应用平台。
或者,通过执行以下步骤之一,复制现有 iOS 版 reCAPTCHA 密钥的 ID:
如需从Google Cloud 控制台复制现有密钥的 ID,请执行以下操作:
前往 reCAPTCHA 页面。
- 在 reCAPTCHA 密钥列表中,将鼠标指针悬停在要复制的密钥上,然后点击 .
- 如需使用 REST API 复制现有密钥的 ID,请使用 projects.keys.list 方法。
- 如需使用 gcloud CLI 复制现有密钥的 ID,请使用 gcloud recaptcha keys list 命令。
拥有 GitHub 账号。
阅读 Apple 隐私权详细信息。
准备 iOS 环境
如需准备开发环境,请执行以下操作:
下载并安装 最新版本的 Xcode,并 创建一个新的空白 iOS 单视图应用。
使用以下方法之一下载 SDK:
CocoaPods
- 下载并安装 CocoaPods。
创建一个 Podfile,并将以下几行代码添加到您的 Podfile:
source "https://github.com/CocoaPods/Specs.git" target 'AppTarget' do # Podfiles must include use_frameworks! or # use_frameworks! :linkage => :static use_frameworks! pod "RecaptchaEnterprise", "18.9.1" ... end运行
pod update以安装所需的依赖项。
Swift Package Manager
在 Xcode 中,依次选择 File > Add Packages ,然后在 搜索 或 Enter Package 网址 字段中输入以下网址:
https://github.com/GoogleCloudPlatform/recaptcha-enterprise-mobile-sdk在 Xcode 对话框中,输入以下详细信息:
- GitHub 用户名。
- 您按照 GitHub 的说明创建的个人访问令牌。个人访问令牌 必须具有 Xcode Sign In 对话框中列出的范围。
Xcode 会安装 SDK 及其所需的依赖项。
Flutter
如需详细了解如何通过 Flutter 使用 reCAPTCHA,请参阅 Flutter 文档。
ReactNative
如需详细了解如何通过 React Native 使用 reCAPTCHA,请参阅 React Native 文档。
直接下载
如果您想将 SDK 及其依赖项下载为 xcframeworks, 请下载客户端。
将 Fraud Defense 与 iOS 应用集成
如需将 Fraud Defense 与 iOS 应用集成,请在 Xcode 中执行以下步骤:
如需使用您创建的 reCAPTCHA 密钥 (KEY_ID) 实例化 SDK,请使用以下代码更新应用:
使用分镜脚本的 Swift
更新
ViewController.swift。import RecaptchaEnterprise class ViewController: UIViewController { var recaptchaClient: RecaptchaClient? override func viewDidLoad() { super.viewDidLoad() Task { do { self.recaptchaClient = try await Recaptcha.fetchClient(withSiteKey: "KEY_ID") } catch let error as RecaptchaError { print("RecaptchaClient creation error: \(String(describing: error.errorMessage)).") } } } }如果应用的最低操作系统版本低于 13,请改用尾随闭包:
import RecaptchaEnterprise class ViewController: UIViewController { var recaptchaClient: RecaptchaClient? override func viewDidLoad() { super.viewDidLoad() Recaptcha.fetchClient(withSiteKey: "KEY_ID") { client, error in guard let client = client else { print("RecaptchaClient creation error: \(error).") return } self.recaptchaClient = client } } }
使用 SwiftUI 的 Swift
创建
ViewModel类。import RecaptchaEnterprise @MainActor class ViewModel: ObservableObject { private var recaptchaClient: RecaptchaClient? init() { Task { do { self.recaptchaClient = try await Recaptcha.fetchClient(withSiteKey: "KEY_ID") } catch let error as RecaptchaError { print("RecaptchaClient creation error: \(String(describing: error.errorMessage)).") } } } }如果应用的最低操作系统版本低于 13,请改用尾随闭包:
import RecaptchaEnterprise class ViewController: UIViewController { var recaptchaClient: RecaptchaClient? override func viewDidLoad() { super.viewDidLoad() Recaptcha.fetchClient(withSiteKey: "KEY_ID") { client, error in guard let client = client else { print("RecaptchaClient creation error: \(error).") return } self.recaptchaClient = client } } }在
ContentView.swift中实例化ViewModel。import SwiftUI import RecaptchaEnterprise struct ContentView: View { @StateObject private var viewModel = ViewModel() var body: some View { } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
Objective-C
如果您的应用是用 Objective-C 编写的,请创建一个虚拟 Swift 文件,并包含以下导入,以确保 Xcode 可以找到并链接 Swift 库。
import Foundation为确保
Swift代码正确链接,请依次前往 目标 > 构建设置 > 始终嵌入 Swift 标准库 ,并验证该选项是否设置为Yes。更新
ViewController.h。#import <RecaptchaEnterprise/RecaptchaEnterprise.h> @interface ViewController : UIViewController @property (strong, atomic) RecaptchaClient *recaptchaClient; @end更新
ViewController.m。@implementation ViewController [Recaptcha fetchClientWithSiteKey:@"KEY_ID" completion:^void(RecaptchaClient* recaptchaClient, NSError* error) { if (!recaptchaClient) { NSLog(@"%@", (RecaptchaError *)error.errorMessage); return; } self->_recaptchaClient = recaptchaClient; } ]; @end
SDK 的初始化可能需要几秒钟才能完成。为缓解此延迟,请尽早初始化客户端,例如在自定义
Application类的onCreate()调用期间。 您不应让界面元素阻止 reCAPTCHA SDK。创建一个按钮调用 reCAPTCHA 并触发
execute()。使用分镜脚本的 Swift
- 在分镜脚本中,创建一个按钮。
- 在
ViewController中创建与您创建的按钮关联的操作。 使用以下代码段调用
execute()方法,传递Login操作以返回 reCAPTCHA 令牌:guard let recaptchaClient = recaptchaClient else { print("RecaptchaClient creation failed.") return } Task { do { let token = try await recaptchaClient.execute(withAction: RecaptchaAction.login) print(token) } catch let error as RecaptchaError { print(error.errorMessage) } }如果应用的最低操作系统版本低于 13,请改用尾随闭包:
guard let recaptchaClient = recaptchaClient else { print("RecaptchaClient creation failed.") return } recaptchaClient.execute(withAction: RecaptchaAction.login) { token, error in if let token = token { print(token) } else { print(error) } }
使用 SwiftUI 的 Swift
使用执行代码更新 ViewModel.swift:
import RecaptchaEnterprise @MainActor class ViewModel: ObservableObject { func execute() { guard let recaptchaClient = self.recaptchaClient else { print("Client not initialized correctly.") return } Task { do { let token = try await recaptchaClient.execute(withAction: RecaptchaAction.login) print(token) } catch let error as RecaptchaError { print(error.errorMessage) } } } }如果应用的最低操作系统版本低于 13,请改用尾随闭包:
guard let recaptchaClient = recaptchaClient else { print("RecaptchaClient creation failed.") return } recaptchaClient.execute(withAction: RecaptchaAction.login) { token, error in if let token = token { print(token) } else { print(error) } }更新 ContentView.swift。
import SwiftUI import RecaptchaEnterprise struct ContentView: View { @StateObject private var viewModel = ViewModel() var body: some View { Button { viewModel.execute() } label: { Text("Execute") }.padding() Spacer() } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
Objective-C
- 在分镜脚本 中,创建一个按钮。
- 在
ViewController中创建与您创建的按钮关联的操作。 调用
execute()方法,传递Login操作以返回 reCAPTCHA 令牌:if (!self->_recaptchaClient) { return; } [recaptchaClient execute:RecaptchaAction.login completion:^void(NSString* _Nullable token, NSError* _Nullable error) { if (!token) { NSLog (@"%@", (RecaptchaError *)error.errorMessage); return; } NSLog (@"%@", token); }];
客户端的
executeAPI 可能需要几秒钟才能完成,例如在网络状况较差的情况下,或者等待后台初始化完成时。确保execute()调用不会阻止界面事件,例如按按钮。测试您的应用:
reCAPTCHA 使用 Apple 的 App Attest 作为其检测引擎的一部分。如果您不打算将具有固定分数的测试密钥用于本地开发,请执行以下操作:
在 Xcode 中,将 App Attest 功能添加到您的应用中。
在项目的
.entitlements文件中,将 App Attest 环境设置为production。
如需清理 Xcode 构建环境,请在 Product 菜单中点击清理构建文件夹 。
如要运行该应用程序,请在 Product 菜单中点击运行 。
在已加载的应用中,点击您之前创建的按钮。
观察调试输出窗口,如果集成正确完成,将返回一个 reCAPTCHA 令牌(字母数字字符串)。
从 getClient 方法 API 迁移到 fetchClient 方法
fetchClient 方法会返回一个 RecaptchaClient
,该客户端会在网络失败时重试初始化。如果应用在创建客户端时没有网络访问权限,客户端会不断重试,并在获取网络时成功初始化。
如果您调用 execute(timeout) 且客户端尚未准备就绪,它会先尝试
初始化,然后再返回令牌或 RecaptchaErrorCode。
以下示例展示了如何从 getClient 迁移到 fetchClient。
使用分镜脚本的 Swift
// Migrate from getClient
func initializeWithGetClient() {
Task {
do {
self.recaptchaClient = try await Recaptcha.getClient(withSiteKey: "KEY_ID")
} catch let error as RecaptchaError {
print("RecaptchaClient creation error: \(String(describing: error.errorMessage)).")
}
}
}
// Migrate to fetchClient
func initializeWithFetchClient() {
Task {
do {
self.recaptchaClient = try await Recaptcha.fetchClient(withSiteKey: "KEY_ID")
} catch let error as RecaptchaError {
print("RecaptchaClient creation error: \(String(describing: error.errorMessage)).")
}
}
}
如果应用的最低操作系统版本低于 13,请改用尾随闭包:
// Migrate from getClient
override func initializeWithGetClient() {
Recaptcha.getClient(withSiteKey: "KEY_ID") { client, error in
guard let client = client else {
print("RecaptchaClient creation error: \(error).")
return
}
self.recaptchaClient = client
}
}
// Migrate to fetchClient
override func initializeWithFetchClient() {
Recaptcha.fetchClient(withSiteKey: "KEY_ID") { client, error in
guard let client = client else {
print("RecaptchaClient creation error: \(error).")
return
}
self.recaptchaClient = client
}
}
使用 SwiftUI 的 Swift
// Migrate from getClient
initializeWithGetClient() {
Task {
do {
self.recaptchaClient = try await Recaptcha.getClient(withSiteKey: "KEY_ID")
} catch let error as RecaptchaError {
print("RecaptchaClient creation error: \(String(describing: error.errorMessage)).")
}
}
}
// Migrate to fetchClient
initializeWithFetchClient() {
Task {
do {
self.recaptchaClient = try await Recaptcha.fetchClient(withSiteKey: "KEY_ID")
} catch let error as RecaptchaError {
print("RecaptchaClient creation error: \(String(describing: error.errorMessage)).")
}
}
}
如果应用的最低操作系统版本低于 13,请改用尾随闭包:
// Migrate from getClient
func initializeWithGetClient() {
super.viewDidLoad()
Recaptcha.getClient(withSiteKey: "KEY_ID") { client, error in
guard let client = client else {
print("RecaptchaClient creation error: \(error).")
return
}
self.recaptchaClient = client
}
}
// Migrate to fetchClient
func initializeWithFetchClient() {
super.viewDidLoad()
Recaptcha.fetchClient(withSiteKey: "KEY_ID") { client, error in
guard let client = client else {
print("RecaptchaClient creation error: \(error).")
return
}
self.recaptchaClient = client
}
}
Objective-C
// Migrate from getClient
@implementation ViewController
[Recaptcha getClientWithSiteKey:@"KEY_ID"
completion:^void(RecaptchaClient* recaptchaClient, NSError* error) {
if (!recaptchaClient) {
NSLog(@"%@", (RecaptchaError *)error.errorMessage);
return;
}
self->_recaptchaClient = recaptchaClient;
}
];
@end
// Migrate to fetchClient
@implementation ViewController
[Recaptcha fetchClientWithSiteKey:@"KEY_ID"
completion:^void(RecaptchaClient* recaptchaClient, NSError* error) {
if (!recaptchaClient) {
NSLog(@"%@", (RecaptchaError *)error.errorMessage);
return;
}
self->_recaptchaClient = recaptchaClient;
}
];
@end
为 API 调用设置超时
您可以使用 withTimeout 属性为 execute API 指定超时值。
Swift
调用
execute时设置超时。Task { do { let token = try await recaptchaClient.execute( withAction: RecaptchaAction.login, withTimeout: 10000) print(token) } catch let error as RecaptchaError { print(error.errorMessage) } }如果应用的最低操作系统版本低于 13,请改用 尾随闭包:
recaptchaClient.execute( withAction: RecaptchaAction.login, withTimeout: 10000 ) { token, error in if let token = token { print(token) } else { print(error) } }
Objective-C
调用
execute时设置超时。[recaptchaClient execute:RecaptchaAction.login witTimeout:10000.0 completion:^void(NSString* _Nullable token, NSError* _Nullable error) { if (!token) { NSLog (@"%@", (RecaptchaError *)error.errorMessage); return; } NSLog (@"%@", token); }];
处理错误
如果您的应用无法成功与 reCAPTCHA 服务通信,则可能是因为 API 遇到了错误。您必须在应用中添加逻辑,以妥善处理此类错误。
如需详细了解常见 API 错误的缓解措施,请参阅 RecaptchaErrorCode。
API 参考文档
如需 iOS 版 reCAPTCHA API 的完整参考信息,请参阅
RecaptchaEnterprise。
后续步骤
要评估 reCAPTCHA 响应令牌,请创建评估。