使用 FirebaseUI 轻松向网页应用添加登录机制

FirebaseUI 是以 Firebase Authentication SDK 为基础构建的库,提供适合在您应用中使用的普适性界面流程。FirebaseUI 具有以下优势:

  • 多提供方 - 支持电子邮件、电话号码、Google、Facebook、Twitter 和 GitHub 登录流程。
  • 帐号关联 - 用于安全地关联用户帐号的流程,支持多家身份服务提供方。
  • 自定义 - 重写 FirebaseUI 的 CSS 样式,使其符合您的应用要求。另外,FirebaseUI 是开源的,因此您可以克隆 (fork) 项目,并根据您的需求对其进行深度定制。
  • 一键注册和自动登录 - 自动集成一键注册,实现快速跨设备登录。
  • 本地化的界面 - 支持 40 多种语言
  • 升级匿名用户 - 可以通过登录/注册升级匿名用户。如需了解详情,请访问升级匿名用户部分。

准备工作

  1. 将 Firebase 身份验证添加到您的网页应用

  2. 通过以下任一选项添加 FirebaseUI:

    1. CDN

      从 Firebase 控制台中,将以下脚本和 CSS 文件添加到页面的 <head> 标记中,位于初始化代码段的下方:

      <script src="https://cdn.firebase.com/libs/firebaseui/3.1.1/firebaseui.js"></script>
      <link type="text/css" rel="stylesheet" href="https://cdn.firebase.com/libs/firebaseui/3.1.1/firebaseui.css" />
      
    2. npm 模块

      使用以下命令,通过 npm 安装 FirebaseUI 及其依赖项:

      $ npm install firebaseui --save
      

      在源代码文件中使用 require 指定以下必需模块:

      var firebase = require('firebase');
      var firebaseui = require('firebaseui');
      
    3. Bower 组件

      使用以下命令,通过 Bower 安装 FirebaseUI 及其依赖项:

      $ bower install firebaseui --save
      

      将所需文件添加到 HTML 中(假设文件位于您的 HTTP 服务器的 bower_components/ 路径中):

      <script src="bower_components/firebaseui/dist/firebaseui.js"></script>
      <link type="text/css" rel="stylesheet" href="bower_components/firebaseui/dist/firebaseui.css" />
      

设置登录方法

您必须先启用并配置您希望支持的登录方法,然后用户才能通过 Firebase 登录。

电子邮件地址和密码

  1. Firebase 控制台中,打开 Authentication(身份验证)部分并启用电子邮件地址和密码身份验证。

  2. 将电子邮件服务提供方 ID 添加到 FirebaseUI signInOptions 列表中。

    ui.start('#firebaseui-auth-container', {
      signInOptions: [
        firebase.auth.EmailAuthProvider.PROVIDER_ID
      ],
      // Other config options...
    });
    
  3. 可选:您可以将 EmailAuthProvider 配置为要求用户输入显示名(默认为 true)。

    ui.start('#firebaseui-auth-container', {
      signInOptions: [
        {
          provider: firebase.auth.EmailAuthProvider.PROVIDER_ID,
          requireDisplayName: false
        }
      ]
    });
    

OAuth 提供方(Google、Facebook、Twitter 和 GitHub)

  1. Firebase 控制台中,打开 Authentication(身份验证)部分并启用指定的 OAuth 提供方登录机制。同时,请确保指定了相应的 OAuth 客户端 ID 和口令。

  2. 同样在 Authentication(身份验证)部分中,确保将呈现登录页的网域作为已获授权的网域列入白名单中。

  3. 将 OAuth 提供方 ID 添加到 FirebaseUI signInOptions 列表中。

    ui.start('#firebaseui-auth-container', {
      signInOptions: [
        // List of OAuth providers supported.
        firebase.auth.GoogleAuthProvider.PROVIDER_ID,
        firebase.auth.FacebookAuthProvider.PROVIDER_ID,
        firebase.auth.TwitterAuthProvider.PROVIDER_ID,
        firebase.auth.GithubAuthProvider.PROVIDER_ID
      ],
      // Other config options...
    });
    
  4. 可选:要指定自定义范围,或按提供方指定自定义 OAuth 参数,您可以传递一个对象(而不仅仅是提供方值):

    ui.start('#firebaseui-auth-container', {
      signInOptions = [
        {
          provider: firebase.auth.GoogleAuthProvider.PROVIDER_ID,
          scopes: [
            'https://www.googleapis.com/auth/plus.login'
          ],
          customParameters: {
            // Forces account selection even when one account
            // is available.
            prompt: 'select_account'
          }
        },
        {
          provider: firebase.auth.FacebookAuthProvider.PROVIDER_ID,
          scopes: [
            'public_profile',
            'email',
            'user_likes',
            'user_friends'
          ],
          customParameters: {
            // Forces password re-entry.
            auth_type: 'reauthenticate'
          }
        },
        firebase.auth.TwitterAuthProvider.PROVIDER_ID, // Twitter does not support scopes.
        firebase.auth.EmailAuthProvider.PROVIDER_ID // Other providers don't need to be given as object.
      ]
    });
    

电话号码

  1. Firebase 控制台中,打开 Authentication(身份验证)部分并启用电话号码登录机制。

  2. 确保将呈现登录页的网域作为已获授权的网域列入白名单中。

  3. 将电话号码提供方 ID 添加到 FirebaseUI signInOptions 列表中。

    ui.start('#firebaseui-auth-container', {
      signInOptions = [
        firebase.auth.PhoneAuthProvider.PROVIDER_ID
      ],
      // Other config options...
    });
    
  4. 可选:您可以使用自定义 reCAPTCHA 参数来配置 PhoneAuthProvider,无论 reCAPTCHA 是否可见(默认为正常)。请参阅 reCAPTCHA API 文档了解详情。

    您也可以设置电话号码输入字段的默认国家/地区。如需完整的代码列表,请参阅支持的国家/地区代码列表。如果未指定,电话号码输入字段将默认为美国 (+1)。

    目前,系统支持以下选项。

    ui.start('#firebaseui-auth-container', {
      signInOptions = [
        {
          provider: firebase.auth.PhoneAuthProvider.PROVIDER_ID,
          recaptchaParameters: {
            type: 'image', // 'audio'
            size: 'normal', // 'invisible' or 'compact'
            badge: 'bottomleft' //' bottomright' or 'inline' applies to invisible.
          },
          defaultCountry: 'GB', // Set default country to the United Kingdom (+44).
          // For prefilling the national number, set defaultNationNumber.
          // This will only be observed if only phone Auth provider is used since
          // for multiple providers, the NASCAR screen will always render first
          // with a 'sign in with phone number' button.
          defaultNationalNumber: '1234567890',
          // You can also pass the full phone number string instead of the
          // 'defaultCountry' and 'defaultNationalNumber'. However, in this case,
          // the first country ID that matches the country code will be used to
          // populate the country selector. So for countries that share the same
          // country code, the selected country may not be the expected one.
          // In that case, pass the 'defaultCountry' instead to ensure the exact
          // country is selected. The 'defaultCountry' and 'defaultNationaNumber'
          // will always have higher priority than 'loginHint' which will be ignored
          // in their favor. In this case, the default country will be 'GB' even
          // though 'loginHint' specified the country code as '+1'.
          loginHint: '+11234567890'
        }
      ]
    });
    

登录

要启动 FirebaseUI 登录流程,请通过传递底层的 Auth 实例来初始化 FirebaseUI 实例。

// Initialize the FirebaseUI Widget using Firebase.
var ui = new firebaseui.auth.AuthUI(firebase.auth());

定义要在其中呈现 FirebaseUI 登录微件的 HTML 元素。

<!-- The surrounding HTML is left untouched by FirebaseUI.
     Your app may use that space for branding, controls and other customizations.-->
<h1>Welcome to My Awesome App</h1>
<div id="firebaseui-auth-container"></div>
<div id="loader">Loading...</div>

指定 FirebaseUI 配置(如支持的提供方、界面自定义和成功回调函数等)。

var uiConfig = {
  callbacks: {
    signInSuccessWithAuthResult: function(authResult, redirectUrl) {
      // User successfully signed in.
      // Return type determines whether we continue the redirect automatically
      // or whether we leave that to developer to handle.
      return true;
    },
    uiShown: function() {
      // The widget is rendered.
      // Hide the loader.
      document.getElementById('loader').style.display = 'none';
    }
  },
  // Will use popup for IDP Providers sign-in flow instead of the default, redirect.
  signInFlow: 'popup',
  signInSuccessUrl: '<url-to-redirect-to-on-success>',
  signInOptions: [
    // Leave the lines as is for the providers you want to offer your users.
    firebase.auth.GoogleAuthProvider.PROVIDER_ID,
    firebase.auth.FacebookAuthProvider.PROVIDER_ID,
    firebase.auth.TwitterAuthProvider.PROVIDER_ID,
    firebase.auth.GithubAuthProvider.PROVIDER_ID,
    firebase.auth.EmailAuthProvider.PROVIDER_ID,
    firebase.auth.PhoneAuthProvider.PROVIDER_ID
  ],
  // Terms of service url.
  tosUrl: '<your-tos-url>',
  // Privacy policy url.
  privacyPolicyUrl: '<your-privacy-policy-url>'
};

最后,呈现 FirebaseUI 身份验证界面:

// The start method will wait until the DOM is loaded.
ui.start('#firebaseui-auth-container', uiConfig);

升级匿名用户

启用匿名用户升级功能

当匿名用户使用永久帐号登录或注册后,您需要确保该用户可以继续其注册之前进行的操作。为此,您只需在配置登录界面时将 autoUpgradeAnonymousUsers 设置为 true 即可(此选项默认处于停用状态)。

处理匿名用户升级时发生的合并冲突

有时,最初以匿名方式登录的用户会尝试升级到一个现有的 Firebase 用户。由于现有用户无法关联到其他现有用户,因此,当发生上述情况时,FirebaseUI 将触发 signInFailure 回调函数并显示错误代码 firebaseui/anonymous-upgrade-merge-conflict。error 对象还将包含永久凭据。应在回调函数中触发使用永久凭据登录的机制来完成登录。要通过 auth.signInWithCredential(error.credential) 完成登录,您必须先保存匿名用户的数据并删除匿名用户。然后,在登录完成后,将数据复制回非匿名用户。以下示例说明了此登录流程的工作原理。

// Temp variable to hold the anonymous user data if needed.
var data = null;
// Hold a reference to the anonymous current user.
var anonymousUser = firebase.auth().currentUser;
ui.start('#firebaseui-auth-container', {
  // Whether to upgrade anonymous users should be explicitly provided.
  // The user must already be signed in anonymously before FirebaseUI is
  // rendered.
  autoUpgradeAnonymousUsers: true,
  signInSuccessUrl: '<url-to-redirect-to-on-success>',
  signInOptions: [
    firebase.auth.GoogleAuthProvider.PROVIDER_ID,
    firebase.auth.FacebookAuthProvider.PROVIDER_ID,
    firebase.auth.EmailAuthProvider.PROVIDER_ID,
    firebase.auth.PhoneAuthProvider.PROVIDER_ID
  ],
  callbacks: {
    // signInFailure callback must be provided to handle merge conflicts which
    // occur when an existing credential is linked to an anonymous user.
    signInFailure: function(error) {
      // For merge conflicts, the error.code will be
      // 'firebaseui/anonymous-upgrade-merge-conflict'.
      if (error.code != 'firebaseui/anonymous-upgrade-merge-conflict') {
        return Promise.resolve();
      }
      // The credential the user tried to sign in with.
      var cred = error.credential;
      // Copy data from anonymous user to permanent user and delete anonymous
      // user.
      // ...
      // Finish sign-in after data is copied.
      return firebase.auth().signInWithCredential(cred);
    }
  }
});

后续步骤

  • 如需详细了解如何使用和自定义 FirebaseUI,请访问 README
  • 如果您发现 FirebaseUI 中存在问题并想报告,请使用 GitHub 问题跟踪工具

发送以下问题的反馈:

此网页
需要帮助?请访问我们的支持页面