כניסה של משתמשים באמצעות פרטי הכניסה השמורים שלהם

יש להשתמש בלקוח הכניסה בהקשה אחת כדי לבקש מהמשתמש הרשאה לאחזר את הנתונים אחד מפרטי הכניסה שהם השתמשו בו בעבר כדי להיכנס לאפליקציה שלכם. האלה פרטי הכניסה יכולים להיות שילוב של חשבון Google או של שם משתמש וסיסמה הם שמרו ב-Google באמצעות Chrome, המילוי האוטומטי של Android או Smart Lock סיסמאות.

ממשק המשתמש לכניסה בהקשה אחת

אחרי שפרטי הכניסה מאוחזרים בהצלחה, אפשר להשתמש בהם בצורה חלקה כניסה של המשתמש לחשבון באפליקציה.

אם המשתמש לא שמר פרטי כניסה, לא יוצג ממשק משתמש ותוכלו לספק את החוויה הרגילה שלך ללא חיבור לחשבון.

איפה כדאי להשתמש בכניסה באמצעות One Tap?

אם האפליקציה מחייבת משתמשים להיכנס לחשבון, יש להציג את ממשק המשתמש בהקשה אחת בכניסה לחשבון מסך. האפשרות הזו יכולה להיות שימושית גם אם כבר יש לך אפשרות של 'כניסה באמצעות חשבון Google' לחצן: כי ניתן להגדיר את ממשק המשתמש של One Tap כך שיציג רק פרטי כניסה שימש בעבר לכניסה, הוא יכול לשמש כתזכורת למשתמשים שלעיתים רחוקות להיכנס באופן שבו הם נכנסו בפעם האחרונה, ולמנוע מהם יצירת חשבונות חדשים באפליקציה.

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

אפליקציות אופציונליות לכניסה צריכות גם להשתמש בכניסה באמצעות הקשה אחת במסכי הכניסה שלהן. מהסיבות שצוינו למעלה.

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

1. הגדרת הלקוח לכניסה באמצעות הקשה אחת

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

אם נכנסים לאפליקציה שלך באמצעות סיסמה, צריך להשתמש ב-setPasswordRequestOptions() כדי להפעיל בקשות לפרטי כניסה לסיסמאות.

אם באפליקציה שלך נעשה שימוש ב'כניסה באמצעות חשבון Google', יש להשתמש ב-setGoogleIdTokenRequestOptions() כדי הפעלה והגדרה של בקשות לאסימוני מזהה של Google:

  • מגדירים את מזהה הלקוח של השרת למזהה שיצרתם ב-Google APIs של Google. לתשומת ליבכם: זהו מזהה הלקוח של השרת שלכם, ולא מזהה הלקוח ב-Android.

  • מגדירים את הלקוח לסינון לפי חשבונות מורשים. כשמפעילים את האפשרות הזו האפשרות הרצויה, הלקוח ב-One Tap רק מבקש מהמשתמשים להיכנס לאפליקציה באמצעות חשבונות Google שהם כבר השתמשו בהם בעבר. פעולה זו יכולה לעזור למשתמשים לחתום בהצלחה כאשר הם לא בטוחים אם כבר יש להם חשבון, או חשבון Google שבו הם השתמשו, ומונעים מהמשתמשים ליצור בטעות חשבון חדש חשבונות באפליקציה.

  • אם אתם רוצים לאפשר למשתמשים להיכנס לחשבון באופן אוטומטי כשהדבר אפשרי, אתם צריכים להפעיל את התכונה עם setAutoSelectEnabled(). כניסה אוטומטית אפשרית כאשר הקריטריונים הבאים:

    • למשתמש יש רק פרטי כניסה אחד שנשמרו לאפליקציה. כלומר, מודל אחד נשמר סיסמה או חשבון Google שמור אחד.
    • המשתמש לא השבית את הכניסה האוטומטית הגדרות חשבון Google.
  • אמנם לא חובה, אבל מומלץ מאוד להשתמש ב-nonce לשפר את אבטחת הכניסה ולהימנע מהתקפות חוזרות. כדאי להשתמש setNonce כדי לכלול צופן חד-פעמי בכל בקשה. לעיון ב- SafetyNet קבלת צופן חד-פעמי לקבלת הצעות ופרטים נוספים על יצירת צופן חד-פעמי.

Java

public class YourActivity extends AppCompatActivity {
  // ...

  private SignInClient oneTapClient;
  private BeginSignInRequest signInRequest;

  @Override
  public void onCreate(@Nullable Bundle savedInstanceState,
                       @Nullable PersistableBundle persistentState) {
      super.onCreate(savedInstanceState, persistentState);

      oneTapClient = Identity.getSignInClient(this);
      signInRequest = BeginSignInRequest.builder()
              .setPasswordRequestOptions(PasswordRequestOptions.builder()
                      .setSupported(true)
                      .build())
              .setGoogleIdTokenRequestOptions(GoogleIdTokenRequestOptions.builder()
                      .setSupported(true)
                      // Your server's client ID, not your Android client ID.
                      .setServerClientId(getString(R.string.default_web_client_id))
                      // Only show accounts previously used to sign in.
                      .setFilterByAuthorizedAccounts(true)
                      .build())
              // Automatically sign in when exactly one credential is retrieved.
              .setAutoSelectEnabled(true)
              .build();
      // ...
  }
  // ...
}

Kotlin

class YourActivity : AppCompatActivity() {
    // ...

    private lateinit var oneTapClient: SignInClient
    private lateinit var signInRequest: BeginSignInRequest

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        oneTapClient = Identity.getSignInClient(this)
        signInRequest = BeginSignInRequest.builder()
            .setPasswordRequestOptions(BeginSignInRequest.PasswordRequestOptions.builder()
                .setSupported(true)
                .build())
            .setGoogleIdTokenRequestOptions(
                BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
                    .setSupported(true)
                    // Your server's client ID, not your Android client ID.
                    .setServerClientId(getString(R.string.your_web_client_id))
                    // Only show accounts previously used to sign in.
                    .setFilterByAuthorizedAccounts(true)
                    .build())
            // Automatically sign in when exactly one credential is retrieved.
            .setAutoSelectEnabled(true)
            .build()
        // ...
    }
    // ...
}

2. חיפוש משתמש מחובר

אם הפעילות שלך יכולה לשמש משתמש מחובר או משתמש שלא מחובר לחשבון, הסטטוס של המשתמש לפני הצגת ממשק המשתמש לכניסה בהקשה אחת.

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

3. הצגת ממשק המשתמש לכניסה בהקשה אחת

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

הלקוח One Tap יקרא ל'מאזינים המוצלחים' אם למשתמש יש פריטים שמורים פרטי הכניסה לאפליקציה. בקרב המאזינים להצלחה, קבלו את הכוונה הממתינה את התוצאה Task ומעבירים אותה ל-startIntentSenderForResult() כדי להתחיל ממשק משתמש לכניסה באמצעות הקשה אחת.

אם למשתמש אין פרטי כניסה שמורים, הלקוח One Tap יקרא ש-נכשל. במקרה הזה לא צריך לעשות שום דבר: אפשר פשוט להמשיך הצגת חוויית המשתמש כשאתם לא מחוברים לחשבון באפליקציה. עם זאת, אם יש תמיכה בתכונה 'הקשה אחת' הרשמה, אתם יכולים להתחיל את התהליך הזה כאן כדי ליצור חשבון בצורה חלקה חוויה אישית. תוכלו להיעזר במאמר יצירת חשבונות חדשים בהקשה אחת.

Java

oneTapClient.beginSignIn(signUpRequest)
        .addOnSuccessListener(this, new OnSuccessListener<BeginSignInResult>() {
            @Override
            public void onSuccess(BeginSignInResult result) {
                try {
                    startIntentSenderForResult(
                            result.getPendingIntent().getIntentSender(), REQ_ONE_TAP,
                            null, 0, 0, 0);
                } catch (IntentSender.SendIntentException e) {
                    Log.e(TAG, "Couldn't start One Tap UI: " + e.getLocalizedMessage());
                }
            }
        })
        .addOnFailureListener(this, new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                // No saved credentials found. Launch the One Tap sign-up flow, or
                // do nothing and continue presenting the signed-out UI.
                Log.d(TAG, e.getLocalizedMessage());
            }
        });

Kotlin

oneTapClient.beginSignIn(signInRequest)
    .addOnSuccessListener(this) { result ->
        try {
            startIntentSenderForResult(
                result.pendingIntent.intentSender, REQ_ONE_TAP,
                null, 0, 0, 0, null)
        } catch (e: IntentSender.SendIntentException) {
            Log.e(TAG, "Couldn't start One Tap UI: ${e.localizedMessage}")
        }
    }
    .addOnFailureListener(this) { e ->
        // No saved credentials found. Launch the One Tap sign-up flow, or
        // do nothing and continue presenting the signed-out UI.
        Log.d(TAG, e.localizedMessage)
    }

4. טיפול בתשובה של המשתמש

תגובת המשתמש להודעת הכניסה בהקשה אחת תדווח לאפליקציה שלך באמצעות השיטה onActivityResult() של הפעילות שלך. אם המשתמש בחר להיכנס, התוצאה תהיה פרטי כניסה שמורים. אם המשתמש סירב להיכנס, על ידי סגירת ממשק המשתמש בהקשה אחת או הקשה מחוץ לו, התוצאה תחזור עם קוד RESULT_CANCELED. האפליקציה שלך צריכה לטפל בשתי האפשרויות.

כניסה באמצעות פרטי כניסה שאוחזרו

אם המשתמש בחר לשתף את פרטי הכניסה עם האפליקציה, אפשר לאחזר אותם על ידי העברה של נתוני Intent מ-onActivityResult() אל הלקוח ב-One Tap getSignInCredentialFromIntent(). פרטי הכניסה יהיו בעלי ערך שאינו null נכס googleIdToken אם המשתמש שיתף עם פרטי כניסה לחשבון Google את האפליקציה, או נכס password שאינו null אם המשתמש שיתף סיסמה שמורה.

השתמשו בפרטי הכניסה כדי לבצע אימות באמצעות הקצה העורפי של האפליקציה.

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

Java

public class YourActivity extends AppCompatActivity {

  // ...
  private static final int REQ_ONE_TAP = 2;  // Can be any integer unique to the Activity.
  private boolean showOneTapUI = true;
  // ...

  @Override
  protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
      super.onActivityResult(requestCode, resultCode, data);

      switch (requestCode) {
          case REQ_ONE_TAP:
              try {
                  SignInCredential credential = oneTapClient.getSignInCredentialFromIntent(data);
                  String idToken = credential.getGoogleIdToken();
                  String username = credential.getId();
                  String password = credential.getPassword();
                  if (idToken !=  null) {
                      // Got an ID token from Google. Use it to authenticate
                      // with your backend.
                      Log.d(TAG, "Got ID token.");
                  } else if (password != null) {
                      // Got a saved username and password. Use them to authenticate
                      // with your backend.
                      Log.d(TAG, "Got password.");
                  }
              } catch (ApiException e) {
                  // ...
              }
              break;
      }
  }
}

Kotlin

class YourActivity : AppCompatActivity() {

    // ...
    private val REQ_ONE_TAP = 2  // Can be any integer unique to the Activity
    private var showOneTapUI = true
    // ...

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        when (requestCode) {
             REQ_ONE_TAP -> {
                try {
                    val credential = oneTapClient.getSignInCredentialFromIntent(data)
                    val idToken = credential.googleIdToken
                    val username = credential.id
                    val password = credential.password
                    when {
                        idToken != null -> {
                            // Got an ID token from Google. Use it to authenticate
                            // with your backend.
                            Log.d(TAG, "Got ID token.")
                        }
                        password != null -> {
                            // Got a saved username and password. Use them to authenticate
                            // with your backend.
                            Log.d(TAG, "Got password.")
                        }
                        else -> {
                            // Shouldn't happen.
                            Log.d(TAG, "No ID token or password!")
                        }
                    }
                } catch (e: ApiException) {
                    // ...
                }
            }
        }
    }
    // ...
}

הפסקת ההצגה של ממשק המשתמש בהקשה אחת

אם המשתמש סירב להיכנס לחשבון, הוא יתקשר למספר getSignInCredentialFromIntent() תקפיץ ApiException עם קוד הסטטוס CommonStatusCodes.CANCELED. במקרה כזה, עליכם להשבית באופן זמני את ממשק המשתמש לכניסה בהקשה אחת, כדי שלא מעצבנים את המשתמשים באמצעות הנחיות חוזרות. הדוגמה הבאה משיגה על ידי הגדרת נכס בפעילות, שבו היא משתמשת כדי לקבוע אם כדי להציע למשתמש כניסה בהקשה אחת; אבל אפשר גם לשמור את הערך SharedPreferences או להשתמש בשיטה אחרת.

חשוב ליישם הגבלת קצב של בקשות כניסה באמצעות 'הקשה אחת'. אם לא עשיתם זאת, והמשתמש ביטל כמה הנחיות ברצף, הלקוח One Tap לא תשלח הודעה למשתמש במשך 24 השעות הבאות.

Java

public class YourActivity extends AppCompatActivity {

  // ...
  private static final int REQ_ONE_TAP = 2;  // Can be any integer unique to the Activity.
  private boolean showOneTapUI = true;
  // ...

  @Override
  protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
      super.onActivityResult(requestCode, resultCode, data);

      switch (requestCode) {
          case REQ_ONE_TAP:
              try {
                  // ...
              } catch (ApiException e) {
                  switch (e.getStatusCode()) {
                      case CommonStatusCodes.CANCELED:
                          Log.d(TAG, "One-tap dialog was closed.");
                          // Don't re-prompt the user.
                          showOneTapUI = false;
                          break;
                      case CommonStatusCodes.NETWORK_ERROR:
                          Log.d(TAG, "One-tap encountered a network error.");
                          // Try again or just ignore.
                          break;
                      default:
                          Log.d(TAG, "Couldn't get credential from result."
                                  + e.getLocalizedMessage());
                          break;
                  }
              }
              break;
      }
  }
}

Kotlin

class YourActivity : AppCompatActivity() {

    // ...
    private val REQ_ONE_TAP = 2  // Can be any integer unique to the Activity
    private var showOneTapUI = true
    // ...

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        when (requestCode) {
            REQ_ONE_TAP -> {
                try {
                    // ...
                } catch (e: ApiException) {
                    when (e.statusCode) {
                        CommonStatusCodes.CANCELED -> {
                            Log.d(TAG, "One-tap dialog was closed.")
                            // Don't re-prompt the user.
                            showOneTapUI = false
                        }
                        CommonStatusCodes.NETWORK_ERROR -> {
                            Log.d(TAG, "One-tap encountered a network error.")
                            // Try again or just ignore.
                        }
                        else -> {
                            Log.d(TAG, "Couldn't get credential from result." +
                                " (${e.localizedMessage})")
                        }
                    }
                }
            }
        }
    }
    // ...
}

5. איך יוצאים מהחשבון

כשמשתמש יוצא מהאפליקציה שלך, יש לקרוא לשיטה signOut() של הלקוח ב-One Tap. קריאה אל signOut() משביתה את הכניסה האוטומטית עד שהמשתמש נכנס שוב לחשבון.

גם אם אתם לא משתמשים בכניסה אוטומטית, השלב הזה חשוב מבטיחה שכאשר המשתמשים יוצאים מהאפליקציה, מצב האימות של כל גם ממשקי ה-API של Play Services שבהם אתם משתמשים יאופסו.

השלבים הבאים

אם הגדרת את הלקוח One Tap כך לאחזר את פרטי הכניסה של Google, האפליקציה שלך יכול עכשיו לקבל אסימונים מזהים של Google שמייצגים את המשתמשים חשבונות Google. נושאי לימוד איך להשתמש באסימונים האלה בקצה העורפי.

אם אתם תומכים ב'כניסה באמצעות חשבון Google', תוכלו גם להשתמש בלקוח One Tap כדי להוסיף תהליך היצירה של החשבון באפליקציה מתבצע בצורה חלקה יותר.