שילוב של Google Cloud Fraud Defense עם אפליקציות ל-iOS

בדף הזה מוסבר איך לשלב את Google Cloud Fraud Defense באפליקציית iOS.

בגלל השונות במכשירים ניידים מבחינת גודל המסך, הביצועים וממשקי המשתמש של האפליקציות, מבחן reCAPTCHA עם תיבת סימון ויזואלית (אני לא רובוט) לא זמין באפליקציות לנייד ל-iOS. במקום זאת, אתם יכולים להטמיע אסטרטגיית אכיפה משלכם, כמו תהליך MFA, כדי לספק נתיב חלופי למימוש שוברים לתנועה חשודה.

ערכת ה-SDK משתמשת ברפלקציה ובקוד דינמי כדי לאפשר עדכון ושיפור של מערכת הזיהוי באפליקציות או בערכות SDK שכבר נפרסו. כדי למנוע הפרעה לאפליקציה, הכיתות שזמינות במערכת מוגבלות לרשימה מבוקרת בקפידה.

לפני שמתחילים

  1. מגדירים את גרסת ה-SDK המינימלית של האפליקציה ל-iOS 15 או יוצרים אפליקציה חדשה לנייד.

  2. הכנת הסביבה ל-reCAPTCHA

  3. יוצרים מפתח reCAPTCHA לפלטפורמת האפליקציות ל-iOS.

    אפשרות נוספת היא להעתיק את המזהה של מפתח reCAPTCHA קיים ל-iOS. כדי לעשות זאת, מבצעים אחת מהפעולות הבאות:

    • כדי להעתיק את המזהה של מפתח קיים ממסוףGoogle Cloud :

      1. עוברים לדף reCAPTCHA.

        מעבר אל reCAPTCHA

      2. ברשימת מפתחות reCAPTCHA, מעבירים את מצביע העכבר מעל המפתח שרוצים להעתיק ולוחצים על .
    • כדי להעתיק את המזהה של מפתח קיים באמצעות API בארכיטקטורת REST, משתמשים ב-method‏ projects.keys.list.
    • כדי להעתיק את המזהה של מפתח קיים באמצעות ה-CLI של gcloud, משתמשים בפקודה gcloud recaptcha keys list.

  4. להיות בעלי חשבון GitHub.

  5. מידע על הפרטיות של Apple

הכנת סביבת iOS

כדי להכין את סביבת הפיתוח:

  1. מורידים ומתקינים את הגרסה האחרונה של Xcode ויוצרים אפליקציית iOS חדשה עם תצוגה יחידה ריקה.

  2. מורידים את ה-SDK באחת מהדרכים הבאות:

    CocoaPods

    1. הורדה והתקנה של CocoaPods
    2. יוצרים 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
      
    3. מריצים את הפקודה pod update כדי להתקין את יחסי התלות הנדרשים.

    Swift Package Manager

    1. ב-Xcode, בוחרים באפשרות File > Add Packages (קובץ > הוספת חבילות) ומזינים את כתובת ה-URL הבאה בשדה Search (חיפוש) או Enter Package URL (הזנת כתובת URL של חבילה):

      https://github.com/GoogleCloudPlatform/recaptcha-enterprise-mobile-sdk
      
    2. בתיבת הדו-שיח Xcode, מזינים את הפרטים הבאים:

      • שם המשתמש ב-GitHub.
      • אסימון גישה אישי שיצרתם באמצעות ההוראות של GitHub. טוקן הגישה האישי צריך לכלול את ההיקפים שמפורטים בתיבת הדו-שיח Xcode Sign In.

      מערכת Xcode מתקינה את ה-SDK ואת יחסי התלות הנדרשים שלו.

    Flutter

    הוראות מפורטות לשימוש ב-reCAPTCHA דרך Flutter זמינות במאמרי העזרה של Flutter.

    ReactNative

    הוראות מפורטות לשימוש ב-reCAPTCHA דרך React Native מופיעות במסמכי העזרה של React Native.

    הורדה ישירה

    1. אם רוצים להוריד את ה-SDK ואת יחסי התלות שלו כ-xcframeworks, צריך להוריד את הלקוח.

שילוב של Fraud Defense באפליקציה ל-iOS

כדי לשלב את Fraud Defense באפליקציית iOS, פועלים לפי השלבים הבאים ב-Xcode:

  1. כדי ליצור מופע של ה-SDK עם מפתח reCAPTCHA (KEY_ID) שיצרתם, מעדכנים את האפליקציה עם הקוד הבא:

    ‫Swift עם סטוריבורד

    1. צריך לעדכן את 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, צריך להשתמש בסגירה מסוג trailing:

      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

    1. יוצרים כיתה 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, צריך להשתמש בסגירה מסוג trailing:

      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
          }
        }
      }
      
    2. יצירת מופע של ViewModel ב-ContentView.swift.

      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

    1. אם האפליקציה כתובה ב-Objective-C, צריך ליצור קובץ Swift פיקטיבי ולכלול את שורת הייבוא הבאה כדי לוודא ש-Xcode יכול למצוא ולקשר את ספריות Swift.

      import Foundation
      
    2. כדי לוודא שקוד Swift מקושר בצורה נכונה, עוברים אל Target > Build Settings > Always Embed Swift Standard Libraries ומוודאים שהאפשרות מוגדרת ל-Yes.

    3. צריך לעדכן את ViewController.h.

      #import <RecaptchaEnterprise/RecaptchaEnterprise.h>
      
      @interface ViewController : UIViewController
      @property (strong, atomic) RecaptchaClient *recaptchaClient;
      @end
      
    4. צריך לעדכן את 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 יכול להימשך כמה שניות. כדי לצמצם את זמן האחזור הזה, כדאי לאתחל את הלקוח מוקדם ככל האפשר, למשל במהלך הקריאה onCreate() של מחלקה מותאמת אישית Application. אל תגדירו רכיבי ממשק משתמש לחסימה ב-reCAPTCHA SDK.

  2. יוצרים לחצן לקריאה ל-reCAPTCHA ולהפעלת execute().

    ‫Swift עם סטוריבורד

    1. בסטוריבורד, יוצרים לחצן.
    2. יוצרים פעולה בViewController שמקושרת ללחצן שיצרתם.
    3. קוראים ל-method‏ 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, צריך להשתמש בסגירה מסוג trailing:

      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

    1. מעדכנים את הקובץ 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, צריך להשתמש בסגירה מסוג trailing:

      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)
        }
      }
      
    2. מעדכנים את הקובץ 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

    1. בסטוריבורד, יוצרים לחצן.
    2. יוצרים פעולה בViewController שמקושרת ללחצן שיצרתם.
    3. מבצעים קריאה לשיטה 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);
      }];
      

    יכול להיות שיחלפו כמה שניות עד שה-API של הלקוח, execute, יסיים את הפעולה. זה קורה למשל אם תנאי הרשת איטיים או אם ה-API ממתין לסיום של אתחול ברקע. מוודאים שהקריאות execute() לא חוסמות אירוע בממשק המשתמש, כמו לחיצה על כפתור.

  3. בודקים את הבקשה:

    1. ‫reCAPTCHA משתמש ב-App Attest של אפל כחלק ממנוע הזיהוי שלו. אם אתם לא מתכננים להשתמש במפתח בדיקה עם ציון קבוע לפיתוח מקומי, אתם צריכים לבצע את הפעולות הבאות:

      1. ב-Xcode, מוסיפים את היכולת App Attest לאפליקציה.

      2. בקובץ .entitlements של הפרויקט, מגדירים את סביבת App Attest ל-production.

    2. כדי לנקות את סביבת build של Xcode, בתפריט Product לוחצים על Clean Build Folder.

    3. כדי להריץ את האפליקציה, בתפריט מוצר, לוחצים על הפעלה.

    4. באפליקציה שנטענה, לוחצים על הלחצן שיצרתם קודם.

    5. מתבוננים בחלון הפלט של ניפוי הבאגים כדי לראות אם מוחזר אסימון reCAPTCHA (מחרוזת אלפאנומרית), שמוחזר אם ההטמעה הצליחה.

מעבר משיטת 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, צריך להשתמש בסגירה מסוג trailing:

// 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)).")
    }
  }
}

אם גרסת מערכת ההפעלה המינימלית של האפליקציה שלך היא מתחת ל-13, צריך להשתמש בסגירה מסוג trailing:

// 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

  1. הגדרת זמן קצוב לתפוגה כשמתקשרים אל 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, צריך להשתמש בסגירה מסוג trailing closure:

      recaptchaClient.execute(
        withAction: RecaptchaAction.login,
        withTimeout: 10000
      ) { token, error in
        if let token = token {
          print(token)
        } else {
          print(error)
        }
      }
    

Objective-C

  1. הגדרת זמן קצוב לתפוגה כשמתקשרים אל 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

לעיון בהפניה מלאה ל-reCAPTCHA API ל-iOS, אפשר לעבור אל RecaptchaEnterprise.

המאמרים הבאים

  • כדי להעריך את טוקן התגובה של reCAPTCHA, יוצרים הערכה.