المصادقة مع Firebase باستخدام حسابات مستندة إلى كلمة المرور باستخدام C++

يمكنك استخدام مصادقة Firebase للسماح للمستخدمين بالمصادقة مع Firebase باستخدام عناوين البريد الإلكتروني وكلمات المرور، وإدارة حسابات تطبيقك المستندة إلى كلمة المرور.

قبل البدء

  1. أضف Firebase إلى مشروع C++.
  2. إذا لم تكن قد ربطت تطبيقك بمشروعك في Firebase، يمكنك إجراء ذلك من خلال وحدة تحكُّم Firebase.
  3. فعِّل تسجيل الدخول باستخدام البريد الإلكتروني أو كلمة المرور:
    1. في وحدة تحكُّم Firebase، افتح قسم المصادقة.
    2. في علامة التبويب طريقة تسجيل الدخول، فعِّل طريقة تسجيل الدخول البريد الإلكتروني/كلمة المرور وانقر على حفظ.

الوصول إلى الصف firebase::auth::Auth

الفئة Auth هي مدخل جميع طلبات البيانات من واجهة برمجة التطبيقات.
  1. إضافة ملفَّي عناوين التطبيقات والمصادقة:
    #include "firebase/app.h"
    #include "firebase/auth.h"
    
  2. في رمز الإعداد، أنشئ فئة firebase::App.
    #if defined(__ANDROID__)
      firebase::App* app =
          firebase::App::Create(firebase::AppOptions(), my_jni_env, my_activity);
    #else
      firebase::App* app = firebase::App::Create(firebase::AppOptions());
    #endif  // defined(__ANDROID__)
    
  3. الحصول على الصف firebase::auth::Auth لـ firebase::App هناك ربط واحد لواحد بين App وAuth.
    firebase::auth::Auth* auth = firebase::auth::Auth::GetAuth(app);
    

إنشاء حساب مستنِد إلى كلمة المرور

لإنشاء حساب مستخدم جديد باستخدام كلمة مرور، أكمِل الخطوات التالية ضمن رمز تسجيل الدخول الخاص بتطبيقك:

  1. عندما يشترك مستخدم جديد باستخدام نموذج الاشتراك في تطبيقك، أكمِل أي خطوات جديدة يحتاج إليها تطبيقك لإثبات ملكية الحساب، مثل التأكّد من أنّ كلمة مرور الحساب الجديد مكتوبة بشكل صحيح وتفي بالمتطلبات المتعلّقة بالتعقيد.
  2. إنشاء حساب جديد من خلال تمرير عنوان البريد الإلكتروني وكلمة المرور للمستخدم الجديد إلى Auth::CreateUserWithEmailAndPassword:
    firebase::Future<firebase::auth::AuthResult> result =
        auth->CreateUserWithEmailAndPassword(email, password);
    
  3. إذا كان برنامجك يتضمّن تكرارًا للتحديثات يتم تشغيله بانتظام (مثلاً 30 أو 60 مرة في الثانية)، يمكنك الاطّلاع على النتائج مرة واحدة لكل تحديث باستخدام Auth::CreateUserWithEmailAndPasswordLastResult:
    firebase::Future<firebase::auth::AuthResult> result =
        auth->CreateUserWithEmailAndPasswordLastResult();
    if (result.status() == firebase::kFutureStatusComplete) {
      if (result.error() == firebase::auth::kAuthErrorNone) {
        const firebase::auth::AuthResult auth_result = *result.result();
        printf("Create user succeeded for email %s\n",
               auth_result.user.email().c_str());
      } else {
        printf("Created user failed with error '%s'\n", result.error_message());
      }
    }
    
    أو إذا كان برنامجك يستند إلى حدث، يمكنك تسجيل طلب معاودة الاتصال في المستقبل.

تسجيل دخول مستخدم باستخدام عنوان بريد إلكتروني وكلمة مرور

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

  1. عندما يسجِّل أحد المستخدمين الدخول إلى تطبيقك، يُرجى إدخال عنوان بريده الإلكتروني وكلمة مروره إلى firebase::auth::Auth::SignInWithEmailAndPassword:
    firebase::Future<firebase::auth::AuthResult> result =
        auth->SignInWithEmailAndPassword(email, password);
    
  2. إذا كان برنامجك يتضمّن تكرارًا للتحديثات يتم تشغيله بانتظام (مثلاً 30 أو 60 مرة في الثانية)، يمكنك الاطّلاع على النتائج مرة واحدة لكل تحديث باستخدام Auth::SignInWithEmailAndPasswordLastResult:
    firebase::Future<firebase::auth::AuthResult> result =
        auth->SignInWithEmailAndPasswordLastResult();
    if (result.status() == firebase::kFutureStatusComplete) {
      if (result.error() == firebase::auth::kAuthErrorNone) {
        const firebase::auth::AuthResult auth_result = *result.result();
        printf("Sign in succeeded for email %s\n",
               auth_result.user.email().c_str());
      } else {
        printf("Sign in failed with error '%s'\n", result.error_message());
      }
    }
    
    أو إذا كان برنامجك يستند إلى حدث، يمكنك تسجيل طلب معاودة الاتصال في المستقبل.

تسجيل معاودة الاتصال في المستقبل

تحتوي بعض البرامج على دوال Update اسمها 30 أو 60 مرة في الثانية الواحدة. على سبيل المثال، تتبع العديد من الألعاب هذا النموذج. يمكن لهذه البرامج استدعاء دوال LastResult لاستطلاع المكالمات غير المتزامنة. ومع ذلك، إذا كان برنامجك يستند إلى الأحداث، قد تفضِّل تسجيل دوال معاودة الاتصال. يتم استدعاء دالة الاستدعاء عند اكتمال المستقبل.
void OnCreateCallback(const firebase::Future<firebase::auth::User*>& result,
                      void* user_data) {
  // The callback is called when the Future enters the `complete` state.
  assert(result.status() == firebase::kFutureStatusComplete);

  // Use `user_data` to pass-in program context, if you like.
  MyProgramContext* program_context = static_cast<MyProgramContext*>(user_data);

  // Important to handle both success and failure situations.
  if (result.error() == firebase::auth::kAuthErrorNone) {
    firebase::auth::User* user = *result.result();
    printf("Create user succeeded for email %s\n", user->email().c_str());

    // Perform other actions on User, if you like.
    firebase::auth::User::UserProfile profile;
    profile.display_name = program_context->display_name;
    user->UpdateUserProfile(profile);

  } else {
    printf("Created user failed with error '%s'\n", result.error_message());
  }
}

void CreateUser(firebase::auth::Auth* auth) {
  // Callbacks work the same for any firebase::Future.
  firebase::Future<firebase::auth::AuthResult> result =
      auth->CreateUserWithEmailAndPasswordLastResult();

  // `&my_program_context` is passed verbatim to OnCreateCallback().
  result.OnCompletion(OnCreateCallback, &my_program_context);
}
يمكن أن تكون دالة معاودة الاتصال أيضًا دالة lambda، إذا كنت تفضّل ذلك.
void CreateUserUsingLambda(firebase::auth::Auth* auth) {
  // Callbacks work the same for any firebase::Future.
  firebase::Future<firebase::auth::AuthResult> result =
      auth->CreateUserWithEmailAndPasswordLastResult();

  // The lambda has the same signature as the callback function.
  result.OnCompletion(
      [](const firebase::Future<firebase::auth::User*>& result,
         void* user_data) {
        // `user_data` is the same as &my_program_context, below.
        // Note that we can't capture this value in the [] because std::function
        // is not supported by our minimum compiler spec (which is pre C++11).
        MyProgramContext* program_context =
            static_cast<MyProgramContext*>(user_data);

        // Process create user result...
        (void)program_context;
      },
      &my_program_context);
}

إجراء مقترَح: تفعيل حماية تعداد البريد الإلكتروني

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

للتخفيف من هذه الخطر، ننصحك بتفعيل الحماية من تعداد البريد الإلكتروني لمشروعك باستخدام أداة Google Cloud gcloud. تجدر الإشارة إلى أنّ تفعيل هذه الميزة يغيّر سلوك إعداد تقارير الأخطاء في مصادقة Firebase، لذا تأكّد من أنّ تطبيقك لا يعتمد على الأخطاء الأكثر تحديدًا.

الخطوات اللاحقة

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

  • في تطبيقاتك، يمكنك الحصول على معلومات الملف الشخصي الأساسية للمستخدم من العنصر firebase::auth::User:

    firebase::auth::User user = auth->current_user();
    if (user.is_valid()) {
      std::string name = user.display_name();
      std::string email = user.email();
      std::string photo_url = user.photo_url();
      // The user's ID, unique to the Firebase project.
      // Do NOT use this value to authenticate with your backend server,
      // if you have one. Use firebase::auth::User::Token() instead.
      std::string uid = user.uid();
    }
    
  • في قاعدة بيانات Firebase في الوقت الفعلي وقواعد أمان Cloud Storage، يمكنك الحصول على رقم تعريف المستخدم الفريد للمستخدم الذي سجّل الدخول من المتغيّر auth واستخدامه للتحكّم في البيانات التي يمكن للمستخدم الوصول إليها.

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

لتسجيل خروج مستخدم، يمكنك الاتصال بالرقم SignOut():

auth->SignOut();