您可以将 Google Cloud Fraud Defense 集成到 iOS 应用中,以评估客户端设备信号,并保护移动用户互动免受自动化滥用行为的影响。
由于移动设备在屏幕尺寸、性能以及应用界面方面存在差异,视觉复选框 reCAPTCHA 验证任务(我不是机器人)不适用于 iOS 移动应用。您可以改为实施自己的分层违规处置策略,例如 MFA 流程,为可疑流量提供替代兑换路径。
该 SDK 利用反射和动态代码,以便在已部署的应用或 SDK 中更新和优化检测系统。 为避免干扰应用,系统中可用的类仅限于经过严格控制的列表。
准备工作
将应用的最低 SDK 版本设置为 iOS 15,或创建新的移动应用。
为 iOS 应用平台创建 reCAPTCHA 密钥。
或者,您也可以通过执行以下任一步骤来复制现有 reCAPTCHA for iOS 密钥的 ID:
如需从 Google Cloud 控制台复制现有密钥的 ID,请执行以下操作:
前往 Google Cloud Fraud Defense 页面。
- 选择密钥标签页。
- 在 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.10.0-beta01" ... end运行
pod update以安装所需的依赖项。
Swift Package Manager
在 Xcode 中,依次选择文件 > 添加软件包,然后在搜索或输入软件包网址字段中输入以下网址:
https://github.com/GoogleCloudPlatform/recaptcha-enterprise-mobile-sdk在 Xcode 对话框中,输入以下详细信息:
- GitHub 用户名。
- 您按照 GitHub 的说明创建的个人访问令牌。个人访问令牌必须具有 Xcode 登录对话框中列出的范围。
Xcode 会安装该 SDK 及其所需的依赖项。
Flutter
如需详细了解如何通过 Flutter 使用 reCAPTCHA,请参阅 Flutter 文档。
React Native
如需详细了解如何通过 React Native 使用 reCAPTCHA,请参阅 React Native 文档。
直接下载
如果您想以 xcframeworks 形式下载 SDK 及其依赖项,请下载客户端。
将 Fraud Defense 与您的 iOS 应用集成
如需将 Fraud Defense 与 iOS 应用集成,请在 Xcode 中按照以下步骤操作:
如需使用您创建的 reCAPTCHA 密钥 (KEY_ID) 实例化 SDK,请使用以下代码更新应用:
Swift(使用 Storyboard)
更新
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 } } }
Swift(使用 SwiftUI)
创建
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代码正确关联,请依次前往 Target > Build Settings > Always Embed Swift Standard Libraries,并验证该选项是否已设置为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(使用 Storyboard)
- 在分镜脚本中,创建一个按钮。
- 在
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) } }
Swift(使用 SwiftUI)
使用执行代码更新 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 菜单中点击 Clean Build Folder。
如需运行应用,请在 Product 菜单中点击 Run。
在已加载的应用中,点击您之前创建的按钮。
在调试输出窗口中观察 reCAPTCHA 令牌(字母数字字符串),如果集成成功,系统会返回该令牌。
从 getClient 方法迁移到 fetchClient 方法
fetchClient 方法会返回一个 RecaptchaClient,该客户端会在发生网络故障时重试初始化。如果应用在创建客户端时没有网络访问权限,客户端会不断重试,并在获取网络后成功初始化。
如果您调用 execute(timeout),但客户端尚未准备就绪,则客户端会尝试先进行初始化,然后再返回令牌或 RecaptchaError。
以下示例展示了如何从 getClient 迁移到 fetchClient。
Swift(使用 Storyboard)
// 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
}
}
Swift(使用 SwiftUI)
// 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
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 withTimeout:10000.0 completion:^void(NSString* _Nullable token, NSError* _Nullable error) { if (!token) { NSLog (@"%@", (RecaptchaError *)error.errorMessage); return; } NSLog (@"%@", token); }];
处理错误
如果您的应用无法成功与 reCAPTCHA 服务通信,则可能是因为 API 遇到了错误。您必须在应用中添加逻辑,以妥善处理此类错误。
如需详细了解常见 API 错误的缓解措施,请参阅 RecaptchaErrorCode。
API 参考文档
如需查看 reCAPTCHA API for iOS 的完整参考文档,请参阅 RecaptchaEnterprise。
后续步骤
要评估 reCAPTCHA 响应令牌,请创建评估。