このページでは、iOS アプリに reCAPTCHA を統合する方法について説明します。
画面サイズ、パフォーマンス、アプリの UI に関してモバイル デバイスは多様なため、視覚的なチェックボックスの reCAPTCHA による確認(私はロボットではありません)は iOS モバイルアプリでは使用できません。代わりに、MFA フローなどの独自の階層型適用戦略を実装し、不審なトラフィックに対する代替的な救済パスを提供できます。
SDK では、リフレクションと動的コードを利用して、すでにデプロイされているアプリケーションや SDK で検出システムを更新、調整できます。アプリケーションとの干渉を避けるために、システムで使用できる一連のクラスは慎重に管理されたリストに制限されています。
始める前に
アプリの最小 SDK を iOS 12 に設定するか、新しいモバイルアプリを作成します。
iOS アプリ プラットフォーム用の reCAPTCHA キーを作成します。
あるいは、次のいずれかの方法で、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.6.0" ... end
pod update
を実行して、必要な依存関係をインストールします。
Swift Package Manager
- Xcode で [File] > [Add Packages] を選択し、[Search] または [Enter Package URL] フィールドに次の URL を入力します:
https://github.com/GoogleCloudPlatform/recaptcha-enterprise-mobile-sdk
[Xcode] ダイアログで次の項目を入力します。
- GitHub のユーザー名。
- GitHub の手順を使用して作成した個人用のアクセス トークン。 個人用アクセス トークンには、[XCode ログイン] ダイアログに表示されているスコープが必要です。
Xcode で SDK と必要な依存関係がインストールされます。
Flutter
Flutter で reCAPTCHA を使用する方法について詳しくは、Flutter のドキュメントをご覧ください。
ReactNative
React Native で reCAPTCHA を使用する方法について詳しくは、React Native のドキュメントをご覧ください。
直接ダウンロード
SDK とその依存関係を xcframework としてダウンロードする場合は、クライアントをダウンロードしてください。
アプリを構成する
Swift または Objective-C でアプリを作成できます。
アプリを設定するには、アプリに次のファイルを追加します。
Swift
アプリが Swift で記述されている場合は、次のインポートを含めます。
import RecaptchaEnterprise
Objective-C
アプリが Objective-C で記述されている場合は、ダミーの Swift ファイルを作成し、次のインポートを含めて、Xcode が Swift ライブラリを検出、リンクできるようにします。
import Foundation
Swift
コードが正しくリンクされていることを確認します。[Target] > [Build Settings] > [Always Embed Swift Standard Libraries] に移動して、オプションがYes
に設定されていることを確認してください。
reCAPTCHA を iOS アプリと統合する
reCAPTCHA を 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)).") } } } }
アプリケーションの最小 OS バージョンが 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)).") } } } }
アプリケーションの最小 OS バージョンが 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
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()
呼び出し時など、できるだけ早くクライアントを初期化します。UI 要素を 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) } }
アプリケーションの最小 OS バージョンが 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) } } } }
アプリケーションの最小 OS バージョンが 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); }];
ネットワークの状態が遅い場合や、バックグラウンドの初期化が完了するのを待機している場合など、クライアントの
execute
API が完了するまでに数秒かかることがあります。execute()
呼び出しが、ボタンの押下など、UI イベントをブロックしていないことを確認します。アプリケーションをテストする
reCAPTCHA は、検出エンジンの一部として Apple の AppAttest を使用します。ローカルでの開発に固定スコアを持つテストキーを使用する予定がない場合は、次の手順を行います。
Xcode で、アプリに App Attest 機能を追加します。
プロジェクトの
.entitlements
ファイルで、App Attest 環境をproduction
に設定します。
Xcode ビルド環境をクリーンアップするには、[Product] メニューで [Clean Build Folder] をクリックします。
アプリケーションを実行するには、[Product] メニューで [Run] をクリックします。
読み込んだアプリケーションで、前に作成したボタンをクリックします。
デバッグ出力ウィンドウを確認します。統合が成功した場合、reCAPTCHA トークン(英数字文字列)が返されます。
method 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)).")
}
}
}
アプリケーションの最小 OS バージョンが 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
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)).")
}
}
}
アプリケーションの最小 OS バージョンが 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 呼び出しのタイムアウトを設定する
execute
API のタイムアウト値は、withTimeout
プロパティを使用して指定できます。
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) } }
アプリケーションの最小 OS バージョンが 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 の応答トークンを評価するため、評価を作成する。