Аутентификация в Firebase с использованием учетных записей на основе пароля с использованием C++

Вы можете использовать Firebase Authentication чтобы позволить вашим пользователям аутентифицироваться в Firebase, используя их адреса электронной почты и пароли, а также управлять учетными записями вашего приложения на основе паролей.

Прежде чем начать

  1. Добавьте Firebase в свой проект C++ .
  2. Если вы еще не подключили свое приложение к проекту Firebase, сделайте это из консоли Firebase .
  3. Включить вход по электронной почте/паролю:
    1. В консоли Firebase откройте раздел Auth .
    2. На вкладке «Метод входа » включите метод входа по электронной почте и паролю и нажмите «Сохранить» .

Доступ к классу firebase::auth::Auth

Класс Auth является шлюзом для всех вызовов API.
  1. Добавьте файлы заголовков Auth и App:
    #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 .

Зарегистрируйте обратный вызов на будущее

В некоторых программах есть функции 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);
}
Функция обратного вызова также может быть лямбдой, если хотите.
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).

  • Максимальная длина пароля (максимальная длина 4096 символов)

Вы можете включить принудительное применение политики паролей в двух режимах:

  • Требовать : попытки регистрации завершаются неудачей, пока пользователь не обновит пароль, соответствующий вашей политике.

  • Уведомление : пользователям разрешено регистрироваться с несоответствующим паролем. При использовании этого режима вам следует проверить, соответствует ли пароль пользователя политике на стороне клиента, и предложить пользователю каким-либо образом обновить свой пароль, если он не соответствует.

Новым пользователям всегда необходимо выбрать пароль, соответствующий вашей политике.

Если у вас есть активные пользователи, мы рекомендуем не включать принудительное обновление при входе в систему, если только вы не собираетесь блокировать доступ для пользователей, пароли которых не соответствуют вашей политике. Вместо этого используйте режим уведомления, который позволяет пользователям входить в систему со своими текущими паролями и информировать их о требованиях, которых не хватает их паролю.

Рекомендуется: включить защиту перечисления электронной почты.

Некоторые методы Firebase Authentication , которые принимают адреса электронной почты в качестве параметров, выдают определенные ошибки, если адрес электронной почты не зарегистрирован, когда его необходимо зарегистрировать (например, при входе в систему с адресом электронной почты и паролем), или зарегистрирован, когда его нельзя использовать (например, при изменении адреса электронной почты пользователя). Хотя это может быть полезно для предложения пользователям конкретных средств защиты, злоумышленники также могут использовать его для обнаружения адресов электронной почты, зарегистрированных вашими пользователями.

Чтобы снизить этот риск, мы рекомендуем вам включить защиту перечисления электронной почты для вашего проекта с помощью инструмента Google Cloud gcloud . Обратите внимание, что включение этой функции меняет поведение отчетов об ошибках 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();
    }
  • В правилах безопасности базы данных реального времени и Cloud Storage Firebase Realtime Database вы можете получить уникальный идентификатор пользователя, вошедшего в систему, из переменной auth и использовать его для управления тем, к каким данным пользователь может получить доступ.

Вы можете разрешить пользователям входить в ваше приложение с использованием нескольких поставщиков аутентификации, связав учетные данные поставщика аутентификации с существующей учетной записью пользователя.

Чтобы выйти из системы, вызовите SignOut() :

auth->SignOut();