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

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

قبل البدء

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

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

فئة Auth هي البوابة لجميع طلبات البيانات من واجهة برمجة التطبيقات.
  1. أضِف ملفَي رأس Auth وApp:
    #include <cassert>
    #include <cstdint>
    
    #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());
      }
    }
    أو إذا كان برنامجك يعتمد على الأحداث، قد تفضّل تسجيل دالة ردّ الاتصال في Future.

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

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

  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());
      }
    }
    أو إذا كان برنامجك يعتمد على الأحداث، قد تفضّل تسجيل دالة ردّ الاتصال في Future.

تسجيل دالة معالجة عند اكتمال Future

تتضمّن بعض البرامج وظائف Update يتم استدعاؤها 30 أو 60 مرة في الثانية. على سبيل المثال، تتّبع العديد من الألعاب هذا النموذج. يمكن لهذه البرامج استدعاء دوال LastResult لاستطلاع المكالمات غير المتزامنة. ومع ذلك، إذا كان برنامجك يعتمد على الأحداث، قد تفضّل تسجيل دوال رد الاتصال. يتم استدعاء دالة ردّ الاتصال عند اكتمال Future.
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:

إعدادات المصادقة

تتيح سياسات كلمات المرور Firebase Authentication متطلبات كلمات المرور التالية:

  • يجب إدخال حرف صغير

  • يجب إدخال حرف كبير

  • يجب إدخال رمز رقمي

  • يجب إدخال حرف غير أبجدي رقمي

    تستوفي الأحرف التالية متطلّبات الأحرف غير الأبجدية الرقمية: ^ $ * . [ ] { } ( ) ? " ! @ # % & / \ , > < ' : ; | _ ~

  • الحد الأدنى لطول كلمة المرور (يتراوح من 6 إلى 30 حرفًا، والقيمة التلقائية هي 6)

  • الحد الأقصى لطول كلمة المرور (الحد الأقصى للطول هو 4,096 حرفًا)

يمكنك تفعيل فرض سياسة كلمات المرور في وضعَين:

  • مطلوب: تتعذّر محاولات الاشتراك إلى أن يغيّر المستخدم كلمة المرور لتصبح متوافقة مع سياستك.

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

يُطلب من المستخدمين الجدد دائمًا اختيار كلمة مرور تتوافق مع سياستك.

إذا كان لديك مستخدمون نشطون، ننصحك بعدم تفعيل خيار "فرض الترقية عند تسجيل الدخول" إلا إذا كنت تنوي حظر وصول المستخدمين الذين لا تتوافق كلمات مرورهم مع سياستك. بدلاً من ذلك، استخدِم وضع الإشعار الذي يتيح للمستخدمين تسجيل الدخول باستخدام كلمات المرور الحالية وإبلاغهم بالمتطلبات التي لا تستوفيها كلمات المرور.

ننصحك بتفعيل ميزة "الحماية من تعداد عناوين البريد الإلكتروني"

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

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

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

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

بعد أن يسجّل المستخدم الدخول للمرة الأولى، يتم إنشاء حساب مستخدم جديد وربطه ببيانات الاعتماد، أي اسم المستخدم وكلمة المرور أو رقم الهاتف أو معلومات مقدّم خدمة المصادقة التي سجّل المستخدم الدخول بها. يتم تخزين هذا الحساب الجديد كجزء من مشروع 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 Realtime Database وCloud Storage قواعد الأمان، يمكنك الحصول على معرّف المستخدِم الفريد للمستخدِم الذي سجّل الدخول من المتغيّر auth، واستخدامه للتحكّم في البيانات التي يمكن للمستخدِم الوصول إليها.

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

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

auth->SignOut();