Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register

使用 Google 登录服务和 C++ 进行身份验证

您可以将 Google 登录机制集成到您的应用中,让您的用户可使用自己的 Google 帐号进行 Firebase 身份验证。

准备工作

  1. 将 Firebase 添加到您的 C++ 项目
  2. 在 Firebase 控制台中启用 Google 登录机制:
    1. Firebase 控制台中,打开 Auth 部分。
    2. 登录方法标签页中,启用 Google 登录方法并点击保存

访问 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::App 对应的 firebase::auth::Auth 类。AppAuth 是一对一的映射关系。
    firebase::auth::Auth* auth = firebase::auth::Auth::GetAuth(app);
    

进行 Firebase 身份验证

  1. 分别按照适用于 AndroidiOS 的说明,获取 ID 令牌用于登录 Google。
  2. 在用户成功登录之后,用 ID 令牌换取 Firebase 凭据,然后使用此 Firebase 凭据进行 Firebase 身份验证:
    firebase::auth::Credential credential =
        firebase::auth::GoogleAuthProvider::GetCredential(google_id_token,
                                                          nullptr);
    firebase::Future<firebase::auth::User*> result =
        auth->SignInWithCredential(credential);
    
  3. 如果您的程序有定期(如每秒 30 次或 60 次)运行的更新循环,则您可以在每次更新时利用 Auth::SignInWithCredentialLastResult 检查一次结果:
    firebase::Future<firebase::auth::User*> result =
        auth->SignInWithCredentialLastResult();
    if (result.status() == firebase::kFutureStatusComplete) {
      if (result.error() == firebase::auth::kAuthErrorNone) {
        firebase::auth::User* user = *result.result();
        printf("Sign in succeeded for `%s`\n", user->display_name().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::User*> 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::User*> 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::auth::User 对象获取用户的基本个人资料信息:

    firebase::auth::User* user = auth->current_user();
    if (user != nullptr) {
      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 变量获取已登录用户的唯一用户 ID,然后利用此 ID 来控制用户可以访问哪些数据。

您可以将身份验证提供方凭据关联至现有用户帐号,让用户可以使用多个身份验证提供方登录您的应用。

如需将用户退出登录,请调用 SignOut()

auth->SignOut();