تسجيل دخول المستخدمين باستخدام بيانات الاعتماد المحفوظة

استخدِم برنامج تسجيل الدخول بنقرة واحدة لطلب إذن من المستخدم أحد بيانات الاعتماد التي استخدموها سابقًا لتسجيل الدخول إلى تطبيقك. هذه يمكن أن تكون بيانات الاعتماد حساب Google أو خليط من اسم المستخدم وكلمة المرور أن يتم حفظه مع Google باستخدام Chrome أو ميزة الملء التلقائي في Android أو Smart Lock كلمات المرور

واجهة مستخدم لتسجيل الدخول بنقرة واحدة

يمكنك استخدام بيانات الاعتماد بسهولة عند استردادها سجِّل دخول المستخدم إلى تطبيقك.

وإذا لم يحفظ المستخدم أي بيانات اعتماد، لن تظهر أي واجهة مستخدم، ويمكنك توفير تجربة تسجيل الخروج المعتادة.

أين يجب تسجيل الدخول باستخدام ميزة "نقرة واحدة"؟

إذا كان تطبيقك يتطلّب من المستخدمين تسجيل الدخول، اعرض واجهة المستخدم بنقرة واحدة عند تسجيل الدخول الشاشة. ويمكن أن يكون ذلك مفيدًا حتى إذا سبق لك تفعيل ميزة "تسجيل الدخول باستخدام حساب Google". الزر: نظرًا لأنه يمكن تهيئة واجهة مستخدم النقرة الواحدة لإظهار بيانات الاعتماد فقط المستخدم سابقًا لتسجيل الدخول، فيمكن أن يكون تذكيرًا للمستخدمين الذين نادرًا ما تسجيل الدخول بطريقة تسجيل الدخول في المرة الأخيرة، ومنعها من الدخول عن طريق الخطأ وإنشاء حسابات جديدة باستخدام تطبيقك

إذا كان تسجيل الدخول اختياريًا لتطبيقك، يمكنك تسجيل الدخول بنقرة واحدة على أي ذات تجربة محسّنة عبر تسجيل الدخول. على سبيل المثال، إذا كان بإمكان المستخدمين تصفُّح المحتوى باستخدام تطبيقك بدون تسجيل الدخول، ولكن يمكنك فقط نشر تعليقات أو إضافة العناصر إلى سلة التسوق بعد تسجيل الدخول، سيكون ذلك سياقًا معقولاً تسجيل الدخول بنقرة واحدة

يجب أن تستخدم التطبيقات الاختيارية لتسجيل الدخول عملية تسجيل الدخول بنقرة واحدة أيضًا على شاشات تسجيل الدخول للأسباب المذكورة أعلاه.

قبل البدء

1. ضبط برنامج تسجيل الدخول بنقرة واحدة

يمكنك ضبط برنامج تسجيل الدخول بنقرة واحدة لتسجيل دخول المستخدمين باستخدام أو كلمات المرور أو حسابات Google المحفوظة أو أي منهما. (يوصى بدعم كليهما، تفعيل إمكانية إنشاء الحساب بنقرة واحدة للمستخدمين الجدد وتسجيل الدخول تلقائيًا أو بنقرة واحدة لأكبر عدد ممكن من المستخدمين المكرّري الزيارة).

إذا كان تطبيقك يستخدم تسجيل الدخول المستنِد إلى كلمة المرور، عليك استخدام setPasswordRequestOptions() من أجل تمكين طلبات بيانات اعتماد كلمة المرور.

إذا كان تطبيقك يستخدم "تسجيل الدخول بحساب Google"، استخدِم setGoogleIdTokenRequestOptions() للأغراض التالية: تمكين وتهيئة طلبات الرمز المميز لمعرّف Google:

  • اضبط معرِّف عميل الخادم على المعرّف الذي أنشأته في Google APIs. وحدة التحكم. لاحظ أن هذا هو معرف العميل الخاص بخادمك، وليس معرِّف عميل Android.

  • اضبط العميل على الفلترة حسب الحسابات المعتمَدة. عند تفعيل هذه الميزة يطلب برنامج "نقرة واحدة" من المستخدمين فقط تسجيل الدخول إلى التطبيق باستخدام حسابات Google التي استخدموها من قبل. ويمكن أن يساعد ذلك المستخدمين على تسجيل بنجاح عندما لا يكونون متأكدين مما إذا كان لديهم حساب بالفعل أو حساب Google الذي استخدموه، وتمنع المستخدمين من إنشاء محتوى جديد عن طريق الخطأ الحسابات المرتبطة بتطبيقك.

  • إذا أردت تسجيل دخول المستخدمين تلقائيًا عندما يكون ذلك ممكنًا، ففعّل الميزة مع setAutoSelectEnabled(). يكون تسجيل الدخول التلقائي ممكنًا عند يتم استيفاء المعايير التالية:

    • لدى المستخدم بيانات اعتماد واحدة فقط محفوظة لتطبيقك. أي، واحد محفوظ كلمة مرور أو حساب Google واحد محفوظ.
    • لم يقم المستخدم بإيقاف تسجيل الدخول التلقائي في إعدادات حساب Google
  • وعلى الرغم من أنّ هذه الخطوة اختيارية، إلا أنّنا ننصحك بشدة بالتفكير في استخدام رقم خاص تحسين أمان عملية تسجيل الدخول وتجنُّب إعادة تشغيل الهجمات. استخدام 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- عرض واجهة المستخدم لتسجيل الدخول بنقرة واحدة

إذا لم يسجّل المستخدم الدخول ولم يرفض استخدام تسجيل الدخول بنقرة واحدة، ولاستدعاء طريقة beginSignIn() لكائن العميل، وإرفاق المستمعين Task، يتم إرجاعه. تنفِّذ التطبيقات ذلك عادةً من خلال طريقة onCreate() للنشاط. أو بعد انتقالات الشاشة عند استخدام بنية نشاط واحد.

سيتصل برنامج "نقرة واحدة" بأداة استماع النجاح إذا كان لدى المستخدم أي مقتطفات محفوظة بيانات الاعتماد لتطبيقك. في المستمع الناجح، احصل على النية المعلقة من نتيجة Task وتمريرها إلى startIntentSenderForResult() لبدء واجهة مستخدم لتسجيل الدخول بنقرة واحدة

إذا لم يكن لدى المستخدم أي بيانات اعتماد محفوظة، فسيتصل برنامج "نقرة واحدة" أداة معالجة الفشل. في هذه الحالة، لا يلزم اتخاذ أي إجراء: يمكنك ببساطة المتابعة تقديم تجربة تسجيل الخروج من التطبيق. في المقابل، إذا كنت توفّر ميزة "نقرة واحدة"، يمكنك بدء هذه العملية هنا لإنشاء حساب سلس المستخدم. راجِع إنشاء حسابات جديدة بنقرة واحدة.

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. ويجب أن يتعامل تطبيقك مع كلا الاحتمالَين.

تسجيل الدخول باستخدام بيانات الاعتماد التي تم استردادها

إذا اختار المستخدم مشاركة بيانات الاعتماد مع تطبيقك، يمكنك استردادها من خلال تمرير بيانات الأهداف من onActivityResult() إلى حساب عميل "نقرة واحدة" طريقة getSignInCredentialFromIntent(). ستحتوي بيانات الاعتماد على قيمة غير فارغة السمة googleIdToken إذا شارك المستخدم بيانات اعتماد حساب Google مع تطبيقك، أو سمة password غير خالية إذا شارك المستخدم كلمة مرور محفوظة.

استخدِم بيانات الاعتماد للمصادقة مع الواجهة الخلفية لتطبيقك.

  • إذا تم استرداد اسم المستخدم وكلمة المرور، استخدِمهما لتسجيل الدخول لو قدّمها المستخدم يدويًا
  • في حال استرداد بيانات اعتماد حساب 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 أو استخدام طريقة أخرى.

من المهم أن تحدّ من معدّل تلقّي رسائل طلب تسجيل الدخول بنقرة واحدة. إذا لم تطلب ذلك، وألغى أحد المستخدمين عدة طلبات على التوالي، فسيطلب برنامج "نقرة واحدة" ولن يتم إرسال طلب إلى المستخدم خلال الـ 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() الخاصة ببرنامج "نقرة واحدة". سيؤدي الاتصال بالرقم signOut() إلى إيقاف تسجيل الدخول التلقائي إلى أن يسجِّل المستخدم الدخول مرة أخرى.

حتى لو لم تكن تستخدم تسجيل الدخول التلقائي، فإن هذه الخطوة مهمة لأنها يضمن أنه عندما يسجّل المستخدمون خروجهم من تطبيقك، ستضمن حالة المصادقة لأي تتم أيضًا إعادة ضبط واجهات برمجة تطبيقات "خدمات Play" التي تستخدمها.

الخطوات التالية

في حال ضبط برنامج "نقرة واحدة" لاسترداد بيانات اعتماد Google، سيحصل تطبيقك الآن، يمكنك الحصول على رموز Google ID المميزة التي تمثل حسابات المستخدمين حسابات Google. التعلّم كيفية استخدام هذه الرموز في الخلفية.

إذا كنت تتيح ميزة "تسجيل الدخول بحساب Google"، يمكنك أيضًا استخدام برنامج "نقرة واحدة" لإضافة وخطوات إنشاء الحسابات بسلاسة إلى تطبيقك.