使用Firebase构建云端应用:创建项目和用户管理

在构建自己的在线云工具应用时,我使用 Firebase 为自己的“无后端项目”提供服务,把在开发期间接触到的一些内容整理在一起,制成系列笔记。这个过程有两个好处:巩固知识点,整理开发过程的思路。因为前端开发是自己所熟悉的领域,所以先从 Firebase 入手,将后端的一些知识点提前梳理理顺,避免后续的学习过程中的卡壳而导致无法坚持。今天第一期:创建项目和用户管理。

什么是 Firebase

Firebase 原本是一家实时后端数据库创业公司,为提供一个实时响应的数据服务。后被 Google 收购,该平台适用在IOS、Android、web前端等各种跨平台上,对于没有数据库处理经验的开发者,只需使用自己熟悉的语言将数据放在Firebase上,再通过Firebase提供的API即可实现实时数据同步。同时 Google 在新版的 Firebase 中包含开发、成长与营收三阶段,并整合分析工具,不过分析工具目前只针对移动 App,网页的话可以继续使用 Google Analytics

何谓“实时数据库”?简单粗暴的理解就是,数据库中数据的变动会互动通知到客户端。同一账号在客户端 A出操作,客户端 B 会收到相应的通知。根据我在浏览器中的调试,发现在 Web 端 原来是用的 WebSocket。考虑到写数据时遇到的无网络连接问题,Firebase的数据库API使用了本地缓存,使得在离线状态下也能保持读写不失败,并且会在网络恢复连接时和服务器进行同步。

Firebase 提供了四种 SDK: Android,IOS,Web 和 C++。我将使用 Web 端 SDK 开发一个无后端的笔记应用。

关联应用

在使用 Firebase 作为后端数据库之前,需要登录 Firebase 的控制台添加一个 Firebase 的网络应用。你可选择新建一个应用,或者导入一个现有的 Google 项目。

创建完应用之后,进入应用的控制面板,在 ‘https://console.firebase.goog...’ 中可以看到硕大的绑定入口“将 Firebase 添加到您的网页应用”,点击之后,将给处的 JavaScript 添加到 HTML 文件中。

<script src="https://www.gstatic.com/firebasejs/3.4.0/firebase.js"></script>
  <script>
    // Initialize Firebase
    let config = {
      apiKey: '<your-api-key>',authDomain: '<your-auth-domain>',databaseURL: '<your-database-url>',storageBucket: '<your-storage-bucket>'
    };
    firebase.initializeApp(config);
  </script>

当然也可通过 npm 安装 Firebase 的 SDK npm link,然后通过 Webpack 等工具打包。

npm install --save firebase

引入 Firebase

let firebase = require('firebase');
let app = firebase.initializeApp({ ... });

完整的 Firebase 客户端包包含了Firebase 的 Authentication,Realtime Database,Storage 和 Cloud Messaging。上面的代码将会把这些功能全部引入。可以将这些功能以独立组件的形式引入,减少代码量。

  • firebase-app 核心代码(必需)

  • firebase-auth Authentication(可选)

  • firebase-database Realtime Database(可选)

  • firebase-storage Storage(可选)

  • firebase-messaging Cloud Messagin(可选)

在这个案例中目前 Storage暂时没有使用的计划,Cloud Messaging 针对的是移动端,所以这两个组件不引入。

let firebase = require('firebase/app');
require('firebase/auth');
require('firebase/database');
 
let app = firebase.initializeApp({ ... });
// ...

完成上述步骤之后,你已经可以在环境中使用 firebase 提供的各种接口了。

用户

大多数应用都需要了解用户的身份。知道用户的身份可以让应用将用户数据安全地保存在云中并跨所有用户设备提供相同的个性化体验。
Firebase Authentication 提供后端服务、易用 SDK 和现成 UI 库来向应用验证用户的身份。它支持使用密码、深受欢迎的联合用户身份提供商(如 Google、Facebook 和 Twitter)等方法进行身份验证。

本次案例使用第三方登录,不使用 Firebase 提供的 UI库,有兴趣的朋友可以自己去试试 https://github.com/firebase/FirebaseUI-Web

添加了 Firebase应用之后,打开console的 Authentication,在登录方法中开启需要的登录提供商。这里我选择了“电子邮件地址/密码”和“Github“两种方式。

创建基于密码的帐户

用户填写表单注册时,完成所需的任何新帐户验证步骤,例如验证新帐号密码键入正确,或者检查账号是否已经存在。然后
邮件地址和密码传递到 createuserWithEmailAndPassword 方法中来创建新帐户:

firebase.auth().signInWithEmailAndPassword(email,password).catch((error) => {
  // Handle Errors here.
  let errorCode = error.code;
  let errorMessage = error.message;
  // ...
});

用户首次登录后,便会建立一个新用户帐户并链接至该用户登录时使用的凭据,即用户名和密码,或身份验证提供程序信息。此新帐户存储在 Firebase 项目中,可用于跨项目中的每个应用识别用户,无论该用户如何登录

使用 Github 账号登录

在console 中的登录方式中启用 github 登录之后,需要添加从 GitHub 获得的 OAuth 2.0 客户端 ID 和客户端密钥。同时将你的 Github 应用的授权回调地址设置为 Firebase OAuth 重定向 URI(例如 my-app-12345.firebaseapp.com/__/auth/handler)。Github 的应用配置

上述前期工作准备就绪之后,可以开始使用 Firebase SDK 来使用登录流程。

先创建一个 GitHub 提供程序对象的实例:

let provider = new firebase.auth.GithubAuthProvider();

然后是一个可选的步骤:从身份验证提供程序中指定您想请求的其他 OAuth 2.0 范围。调用 Provider 实例的 addScope方法添加范围。例如:

provider.addScope('repo');

详细参数可以参考身份验证提供程序文档

接下来,使用 GitHub 提供程序对象进行 Firebase 身份验证。可以提示用户,让其通过打开弹出式窗口或重定向登录页面方法以自己的 GitHub account 登录。移动设备最好使用重定向方法。要用弹出式窗口的方法登录调用 signInWithPopup:

firebase.auth().signInWithPopup(provider).then(function(result) {
  // This gives you a GitHub Access Token. You can use it to access the GitHub API.
  let token = result.credential.accesstoken;
  // The signed-in user info.
  let user = result.user;
  // ...
}).catch(function(error) {
  // Handle Errors here.
  let errorCode = error.code;
  let errorMessage = error.message;
  // The email of the user's account used.
  let email = error.email;
  // The firebase.auth.AuthCredential type that was used.
  let credential = error.credential;
  // ...
});

你可以检索 GitHub 提供程序的 OAuth 令牌,使用该令牌可通过 GitHub API 提取额外数据。
还可以通过这种方法捕获并处理错误获取错误代码列表

如果要用重定向登录页面方法登录,则调用 signInWithRedirect:

firebase.auth().signInWithRedirect(provider);

不仅如此,你还可以在页面加载时通过调用 getRedirectResult 检索 GitHub 提供程序的 OAuth 令牌:

firebase.auth().getRedirectResult().then(function(result) {
  if (result.credential) {
    // This gives you a GitHub Access Token. You can use it to access the GitHub API.
    let token = result.credential.accesstoken;
    // ...
  }
  // The signed-in user info.
  let user = result.user;
}).catch(function(error) {
  // Handle Errors here.
  let errorCode = error.code;
  let errorMessage = error.message;
  // The email of the user's account used.
  let email = error.email;
  // The firebase.auth.AuthCredential type that was used.
  let credential = error.credential;
  // ...
});

当然,你也可以手动处理登录流程。 在 GitHub 登录流程结束后,你会收到一个 OAuth 2.0 访问令牌。在用户使用 GitHub 成功登录之后,先使用 OAuth 2.0 访问令牌换取 Firebase 凭据:

let credential = firebase.auth.GithubAuthProvider.credential(token);

然后使用 Firebase 凭据进行 Firebase 身份验证:

firebase.auth().signInWithCredential(credential).catch(function(error) {
  // Handle Errors here.
  let errorCode = error.code;
  let errorMessage = error.message;
  // The email of the user's account used.
  let email = error.email;
  // The firebase.auth.AuthCredential type that was used.
  let credential = error.credential;
  // ...
});

除了前面提到的邮箱密码验证,第三方 OAuth 验证之外,Firebase 还支持自定义身份认证系统和匿名身份验证,这里不讲,有兴趣和需求的朋友可以自己去了解。

其他用户管理操作的支持

要注销用户调用 signOut:

firebase.auth().signOut().then(() => {
  // Sign-out successful.
},function(error) {
  // An error happened.
});

除此之外,SDK 还提供了一系列用户管理的方法

获取当前用户的推荐方法是在 Auth 对象上调用onAuthStateChanged方法,这可确保在您获取当前用户时,Auth 对象不会处于中间状态,例如初始化。既要么未登录,要么已登录

firebase.auth().onAuthStateChanged((user) => {
  if (user) {
    // User is signed in.
  } else {
    // No user is signed in.
  }
});

也可以使用 currentUser 属性获取当前已登录用户。 如果用户没有登录,currentUser 则为 null:

let user = firebase.auth().currentUser;

if (user) {
  // User is signed in.
} else {
  // No user is signed in.
}

不过有一点要注意,currentUser 还可能由于 auth 对象尚未完成初始化而为 null。 如果使用观察程序跟踪用户登录状态,则无需处理该情况。
获取用户对象的实例之后,可以访问实例上的一些属性,以及调用实例上的一些方法用户进行一些操作,比如:

let user = firebase.auth().currentUser;
let name,email,photoUrl,uid;

if (user != null) {
  name = user.displayName;
  email = user.email;
  photoUrl = user.photoURL;
  uid = user.uid;  // 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 User.getToken() instead.
}
let user = firebase.auth().currentUser;

if (user != null) {
  user.providerData.forEach(function (profile) {
    console.log("Sign-in provider: "+profile.providerId);
    console.log("  Provider-specific UID: "+profile.uid);
    console.log("  Name: "+profile.displayName);
    console.log("  Email: "+profile.email);
    console.log("  Photo URL: "+profile.photoURL);
  });
}
let user = firebase.auth().currentUser;

user.updateProfile({
  displayName: "Jane Q. User",photoURL: "https://example.com/jane-q-user/profile.jpg"
}).then(function() {
  // Update successful.
},function(error) {
  // An error happened.
});
let user = firebase.auth().currentUser;

user.updateEmail("user@example.com").then(function() {
  // Update successful.
},function(error) {
  // An error happened.
});

要设置用户的电子邮件地址,该用户必须最近登录。在 Firebase 控制台的"Authentication"的"Email Templates"页面中允许自定义使用的电子邮件模板。

let user = firebase.auth().currentUser;
let newPassword = getASecureRandomPassword();

user.updatePassword(newPassword).then(function() {
  // Update successful.
},function(error) {
  // An error happened.
});

也可以在控制台中手动删除用户

let user = firebase.auth().currentUser;

user.delete().then(function() {
  // User deleted.
},function(error) {
  // An error happened.
});

有些安全敏感性操作,比如删除帐户、设置主电子邮件地址和更改密码,需要用户最近登录过才能执行。如果要执行这些操作中的某一项,而用户只是在很久以前登录过,操作便出错。发生这种错误时,需要从用户获取登录凭据,将该凭据传给 reauthenticate ,对该用户重新进行身份验证。

let user = firebase.auth().currentUser;
let credential;

// Prompt the user to re-provide their sign-in credentials

user.reauthenticate(credential).then(function() {
  // User re-authenticated.
},function(error) {
  // An error happened.
});

结束

如此一来,我的应用已经可以支持邮箱密码登录,github 账号登录。而且用户的管理操作也有很直接明了的方法。当用户添加之后,接下来就可以围绕用户设计出需要的数据结构了。下回:数据结构的定义及数据的操作,敬请期待

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...
在平时工作中的某些场景下,你可能想在整个组件树中传递数据,但却不想手动地通过 props 属性在每一层传递属性,contextAPI 应用而生。
楼主最近入职新单位了,恰好新单位使用的技术栈是 react,因为之前一直进行的是 vue2/vue3 和小程序开发,对于这些技术栈实现机制也有一些了解,最少面试...
我们上一节了了解了函数式组件和类组件的处理方式,本质就是处理基于 babel 处理后的 type 类型,最后还是要处理虚拟 dom。本小节我们学习下组件的更新机...
前面几节我们学习了解了 react 的渲染机制和生命周期,本节我们正式进入基本面试必考的核心地带 -- diff 算法,了解如何优化和复用 dom 操作的,还有...
我们在之前已经学习过 react 生命周期,但是在 16 版本中 will 类的生命周期进行了废除,虽然依然可以用,但是需要加上 UNSAFE 开头,表示是不安...
上一小节我们学习了 react 中类组件的优化方式,对于 hooks 为主流的函数式编程,react 也提供了优化方式 memo 方法,本小节我们来了解下它的用...
开源不易,感谢你的支持,❤ star me if you like concent ^_^
hel-micro,模块联邦sdk化,免构建、热更新、工具链无关的微模块方案 ,欢迎关注与了解
本文主题围绕concent的setup和react的五把钩子来展开,既然提到了setup就离不开composition api这个关键词,准确的说setup是由...
ReactsetState的执行是异步还是同步官方文档是这么说的setState()doesnotalwaysimmediatelyupdatethecomponent.Itmaybatchordefertheupdateuntillater.Thismakesreadingthis.staterightaftercallingsetState()apotentialpitfall.Instead,usecom