Skip to content

Latest commit

 

History

History
723 lines (555 loc) · 30.3 KB

File metadata and controls

723 lines (555 loc) · 30.3 KB

三、将 Firebase 用于认证

在上一章中,我们学习了如何将 Firebase 与 ReactJS 集成,以及如何在 JSX 中创建组件。我们还了解了如何与 DOM 元素交互以获取onSubmit表单值,并将其发送到 Firebase 数据库,以便在云中存储和同步表单数据。React 使用一个快速的、内部的、合成的 DOM 来执行 diff,并为组件所在的位置计算最有效的 DOM 变异。

在本章中,我们将使用 React 和 JSX 创建一个login组件,以使用 Firebase 认证功能保护我们的帮助台应用程序,该功能只允许授权用户查看和添加新票据。

以下是我们将在本章中重点关注的要点列表:

  • 使用 Node.js 进行 React 和 Firebase 设置
  • 带有 React 和 JSX 的复合组件
  • Firebase 认证配置
  • 自定义认证
  • 通过 Facebook 和 Google 进行第三方认证

使用 Node.Js 进行 React 和 Firebase 设置

之前,我们使用纯 JavaScript 创建了 React 应用程序;现在,我们需要使用节点对 React 和 Firebase 设置执行相同的操作。为此,我们必须在系统中安装 Node.js 和npm;如果没有,请先从下载 Node.jshttps://nodejs.org/en/download/ 。安装完成后,运行以下命令以确保节点和npm安装正确:

对于节点,请使用以下命令:

node -v

对于npm,请使用以下内容:

npm -v

命令的输出应如下所示:

现在我们需要安装create-react-app模块,该模块提供初始和默认设置,并让我们快速启动 React 应用程序。在 CMD 中运行以下命令,它将全局安装create-react-app模块(即在命令后面附加-g--global

npm install -g create-react-app 
or 
npm i -g create-react-app

安装完成后,在需要创建项目的本地目录中运行下一个命令;将为 React 生成快速启动项目,无需生成配置:

create-react-app <project-name> 
or
create-react-app login-authentication

这是安装完成后我们的文件夹结构的外观:

在这里,我们完成了 React 的设置;现在,我们安装firebase npm包并集成现有的应用程序。

运行以下命令安装firebase npm包:

npm install firebase --save

安装 firebase 后,在src文件夹中创建一个名为 firebase 的文件夹。

src文件夹中,创建一个名为firebase-config.js的文件,该文件将承载我们项目的配置详细信息:

import firebase from 'firebase';

const config = {
 apiKey: "AIzaSyDO1VEnd5VmWd2OWQ9NQuh-ehNXcoPTy-w",
 authDomain: "demoproject-7cc0d.firebaseapp.com",
 databaseURL: "https://demoproject-7cc0d.firebaseio.com",
 projectId: "demoproject-7cc0d",
 storageBucket: "demoproject-7cc0d.appspot.com",
 messagingSenderId: "41428255556"
};
firebase.initializeApp(config);

export default firebase;

类似地,我们需要使用导入和导出关键字在节点中集成现有组件视图票证和addTicket,并使用npm命令,我们需要安装 React 和 firebase 模块及其依赖项。

您的package.json应该是这样的:

//package.json
{
 "name": "login-authentication",
 "version": "0.1.0",
 "private": true,
 "dependencies": {
 "firebase": "^4.8.0",
 "react": "^16.2.0",
 "react-dom": "^16.2.0",
 "react-router-dom": "^4.2.2",
 "react-scripts": "1.0.17",
 "react-toastr-basic": "^1.1.14"
 },
 "scripts": {
 "start": "react-scripts start",
 "build": "react-scripts build",
 "test": "react-scripts test --env=jsdom",
 "eject": "react-scripts eject"
 }
}

此外,这也是集成现有应用程序后应用程序文件夹结构的外观:

用于认证的 Firebase 配置

Firebase 认证是通过安全规则授予用户读/写访问权限的一项非常令人印象深刻的功能。我们尚未在帮助台应用程序中涵盖或添加安全规则。Firebase 为我们提供了使用自己的电子邮件/密码以及针对 Google、Facebook、Twitter 和 GitHub 的 OAuth 2 集成进行认证的能力。我们还将把我们自己的 auth 系统与 Firebase 集成,以允许访问帮助台应用程序,并允许用户在我们的系统上创建帐户。

让我们看一看 FixBaseServices 的认证列表,并执行以下步骤来为我们的应用程序提供 FielBasic 认证:

  1. 打开http://firebase.google.com 并使用您的凭据登录
  2. 单击左侧部分“开发”选项卡内的“认证”选项:

在前面的屏幕截图中,如果您可以看到,我们在“认证”部分提供了四个选项卡,并且我们使用自定义电子邮件/密码选项启用了提供商的认证,我们可以将其添加到用户选项卡和谷歌认证中:

  • 用户:在这里,我们可以管理和添加多个用户的电子邮件 ID 和密码,以便在不编写任何服务器端代码的情况下向各种提供商进行认证。
  • 登录方法:在本节中,我们可以看到 firebase 中可用的提供者列表。我们还可以管理授权域,防止用户使用相同的电子邮件地址和登录配额。
  • 模板:此功能允许我们在用户使用电子邮件和密码注册时自定义 firebase 发送的电子邮件模板。我们还可以自定义密码重置、电子邮件地址更改和短信验证的模板。

在本章中,我们将介绍这三种认证:

  • 脸谱网
  • 谷歌
  • 电子邮件/密码

使用 Facebook 进行认证

若要将 Facebook 认证添加到我们的帮助台应用程序中,如果您还没有 Facebook 帐户,则需要使用它创建一个帐户。否则,我们需要登录 Facebook 开发者论坛https://developers.facebook.com/apps 。登录后,它会显示应用程序列表和“添加新应用程序”按钮,以创建用于认证的新应用程序 ID。请看以下内容以供参考:

单击添加新应用程序按钮;它显示用于添加应用程序名称的弹出窗口。然后,单击创建应用程序 Id,将您重定向到我们应用程序的仪表板:

This is a screenshot of Facebook developer application dashboard. The Purpose of the image is just to show the list of APIs or Products provided by Facebook to integrate with any web application.

目前,我们需要选择 Facebook 登录进行设置:

如果您可以看到前面的屏幕截图,我们需要为客户端 OAuth 进行设置。为此,我们首先需要启用嵌入式浏览器 OAuth 登录功能来控制 OAuth 登录的重定向,然后复制有效的 OAuth 重定向 URL,当我们在 Firebase 中启用 Facebook 提供程序时可以得到这些 URL。

要在 Firebase 中启用 Facebook 认证,我们需要从 Facebook 应用程序仪表板复制应用程序 ID应用程序机密

然后,将这些复制的值放入 firebase 输入字段,复制重定向 URI,并将其粘贴到客户端 OAuth 设置。另外,启用 facebook 认证,然后单击保存按钮,如下图所示:

这是我们最不需要在 Facebook 开发者论坛和 firebase 中进行 Facebook 认证的事情。

单击“保存”,请注意,提供程序的状态现在已启用:

现在,单击该部分左侧的数据库,并转到规则面板;它应该是这样的:

The purpose of the image is to show the list of tabs under the Realtime Database section and under the Rules tab. Here, we can add the security rules for our database to secure our data and with the help of SIMULATOR we can verify whether it's working as expected or not.

在我们的应用程序的早期,每个人都有权对我们的应用程序和数据库读写数据。现在,我们将更改前面的规则配置,以便只有授权用户才能访问应用程序并将数据写入数据库。查看给定代码并发布更改:

{
 "rules": {
 ".read": "auth != null",
 ".write": "auth != null"
 }
}

使用 React 创建登录表单以进行认证

正如我们已经完成 Firebase 和 Facebook 的认证配置并为其他提供商启用了这些功能一样,现在我们将在 react 中创建一个登录表单,以确保应用程序的安全,该应用程序始终验证用户是否登录;它会将用户重定向到登录页面。因此,让我们创建一个登录页面,并根据路径 URL 配置 React 路由以重定向用户。

从 firebase 文件夹打开firebase-config.js并使用不同的提供者导出以下对象,以便我们可以在应用程序中访问这些对象:

export const firebaseApp = firebase.initializeApp(config);
export const googleProvider = new firebase.auth.GoogleAuthProvider();
export const facebookProvider = new firebase.auth.FacebookAuthProvider();

在前面的代码中,new firebase.auth.GoogleAuthProvider()将为我们提供向 Google API 验证用户身份的方法。

同样,新的firebase.auth.FacebookAuthProvider()将为我们提供使用 Facebook API 对用户进行认证的方法。

打开app.js并将以下代码添加到构造函数中,以初始化应用程序的状态:

constructor() {
super(); 
  this.state = {
   authenticated : false,
   data:''
  }
}

这里,我们将 authenticated 的默认值设置为 false,因为这是应用程序的初始状态,并且用户尚未使用 Firebase 进行认证;在组件的初始状态下,数据的默认值为空。我们将在用户登录时更改这些状态。

首先,我们在login.js中创建Login组件,并在constructor()中设置该组件的初始状态:

 constructor() {
 super();
   this.state = {
     redirect: false
   }
 }

我们已经在初始状态设置了 redirectfalse的默认值,但是每当用户登录和注销时,该值都会改变:

if(this.state.redirect === true){
 return <Redirect to = "/" />
 }
 return (
 <div className="wrapper">
 <form className="form-signin" onSubmit={(event)=>{this.authWithEmailPassword(event)}} ref={(form)=>{this.loginForm = form}}> 
 <h2 className="form-signin-heading">Login</h2>
 <input type="email" className="form-control" name="username" placeholder="Email Address" ref={(input)=>{this.emailField = input}} required />
 <input type="password" className="form-control" name="password" placeholder="Password" ref={(input)=>{this.passwordField = input}} required /> 
 <label className="checkbox">
 <input type="checkbox" value="remember-me" id="rememberMe" name="rememberMe"/> Remember me
 </label>
 <button className="btn btn-lg btn-primary btn-block btn-normal" type="submit">Login</button> 
 <br/> 
<!-- Here we will add the buttons for google and facebook authentication
 </form>
 </div>
 );

render方法中,我们将检查状态并将用户重定向到不同的路由<Redirect>。它将覆盖历史堆栈中的当前路由,就像服务器端重定向(HTTP 3xx)一样。

下面是我们可以用于Redirect组件的属性列表:

  • to:String:我们也使用了重定向 URL。
  • to:Object:带有参数和其他配置(如状态)的位置 URL。考虑这个例子:
<Redirect to={{
 pathname: '/login',
 search: '?utm=your+selection',
 state: { referrer: currentLocation }
}}/>
  • : bool:如果为真,重定向会将新条目推送到历史记录上,而不是替换当前条目。
  • from: string:从旧 URL 重定向的 URL。这只能用于匹配<Switch>内部的位置。考虑这个例子:
<Switch>
 <Redirect from='/old-url' to='/new-url'/>
 <Route path='/new-url' component={componentName}/>
</Switch>

All the preceding <Redirect> features are only available in React Router V4.

我们为登录表单添加了 JSX,并绑定了 methods 和 ref 属性以访问表单值。我们还添加了 Facebook 和谷歌认证按钮。只需查看以下代码:

 <!-- facebook button that we have bind with authWithFacebook()-->
<button className="btn btn-lg btn-primary btn-facebook btn-block" type="button" onClick={()=>{this.authWithFacebook()}}>Login with Facebook</button> 
<!-- Google button which we have bind with authWithGoogle()-->
 <button className="btn btn-lg btn-primary btn-google btn-block" type="button" onClick={()=>{this.authWithGoogle()}}>Login with Google</button>

app.js中,我们配置了如下路由:

<Router>
<div className="container"> {
this.state.authenticated
?
(
<React.Fragment>
<Header authenticated = {this.state.authenticated}/>
<Route path="/" render={() => (<Home userInfo = {this.state.data} />)} />
<Route path="/view-ticket" component={ViewTicketTable}/>
<Route path="/add-ticket" component={AddTicketForm}/>
</React.Fragment>
)
:
(
<React.Fragment>
<Header authenticated = {this.state.authenticated}/>
<Route exact path="/login" component={Login}/>
</React.Fragment>
)
}
</div>
</Router>

在前面的代码中,我们使用的是 React 路由版本 4,它是 React 包的完全重写路由。在以前版本的 React router 中,他们使用了非常困难的配置,这将很难理解,而且,我们需要创建一个单独的组件来管理布局。在路由 V4 中,一切都作为一个组件工作。

In React router V4, we need to import from react-router-dom, not from react-router, as we do in V3. The <Router> component and all other subcomponents get rendered if the route path matches.

使用<React.Fragment>标记,我们可以包装任何 JSX 组件,而无需向 DOM 中添加另一个节点。

In V4 react router, there is no more <IndexRoute>; using <Route exact> will do the same thing.

现在,我们将更改具有导航的标题组件,并添加登录和注销链接:

class Header extends Component {
render() {
 return (
 <div className="navbar navbar-inverse firebase-nav" role="navigation">
 {
 this.props.authenticated
 ?
 (
 <React.Fragment>
 <ul className="nav navbar-nav">
 <li className="active"><Link to="/">Home</Link></li>
 <li><Link to="/view-ticket">Tickets</Link></li>
 <li><Link to="/add-ticket">Add new ticket</Link></li>
 </ul>
 <ul className="nav navbar-nav navbar-right">
 <li><Link to="/logout">Logout</Link></li>
 </ul>
 </React.Fragment>
 ):(
 <React.Fragment>
 <ul className="nav navbar-nav navbar-right">
 <li><Link to="/login">Register/Login</Link></li>
 </ul>
 </React.Fragment>
 )
 }
 </div>
 );
 }
}

如果我们正在使用 React 路由,则有必要使用此选项。让我们在导航中添加<link>而不是<a>标记,并将href属性替换为to。在 V4 中,我们也可以使用<NavLink>;它的工作原理与<Link>相同,但为我们提供了添加额外样式的方法。请看以下代码:

<li><NavLink to="/view-ticket/" activeClassName="active" activeStyle={{fontWeight: 'bold', color: red'}} exact strict>Tickets</NavLink></li>

基于认证,我们将使用登录和注销链接更新导航。

通过在命令提示符下运行以下命令再次启动服务器:

npm start

服务器启动后,打开浏览器并快速查看:

如果您只需查看前面的屏幕摘录并注意地址栏,我尝试打开另一个 URL 来查看票证,但除了标题登录链接外,它没有显示任何内容;现在,如果我们单击 Login,它将呈现登录表单。请参阅以下屏幕截图;应该是这样的:

令人惊讶的是,我们的登录表单看起来很棒,正如预期的那样。

For more information about react router, you can go through https://reacttraining.com/react-router/web/api.

使用 Facebook 进行认证

每一个按钮的onClick都将指向三个验证用户身份的功能。Facebook 验证方法将处理我们与 Firebase 的认证,如下所示:

 authWithFacebook(){
 console.log("facebook");
 firebaseApp.auth().signInWithPopup(facebookProvider).then((result,error)=>{
 if(error){
   console.log("unable to sign in with facebook");
 }
 else{
   this.setState({redirect:true})
 }}).catch((error)=>{
        ToastDanger(error.message);
    })
 }

在这里,我们从 firebaseauth模块调用signInWithPopup()方法并传递给 facebook 提供商。

To display the error messages on UI, we are using React Toaster module and passing those messages into it (don't forget to install and import the React Toaster module before using it). We also need to bind authWithFacebook() methods into the constructor. npm install --save react-toastr-basic

// In app.js import the container import ToastrContainer from 'react-toastr-basic';

//Inside the render method <ToastrContainer />

constructor() {
 super();
 this.authWithFacebook = this.authWithFacebook.bind(this);
 this.state = {
  redirect: false,
  data:null
 }}

现在,当我们单击“使用 Facebook 登录”按钮时,它将打开一个弹出窗口,让我们可以选择使用 Facebook 帐户登录,如图所示:

signInWithPopup()有一个 promise API,允许我们调用.then()并传入回调。此回调将提供一个结果对象,其中包含一个名为user的对象,该对象包含刚刚成功登录的用户的所有信息,包括其姓名、电子邮件和用户照片 URL。我们将使用setState()将此对象存储在状态内部,并在 UI 上显示用户的姓名、电子邮件和照片:

谷歌认证

同样,我们可以在应用程序中配置 Google 认证;只需在authWithGoogle()方法中添加以下代码,即可打开弹出窗口,使用 Google 登录:

 authWithGoogle(){
 console.log("Google");      
 googleProvider.addScope('profile');
 googleProvider.addScope('email');
 firebaseApp.auth().signInWithPopup(googleProvider).then((result,error)=>{
   if(error){
     console.log("unable to sign in with google");
    }
   else{
     this.setState({redirect:true,data:result.user})
   }}).catch((error)=>{
        ToastDanger(error.message);
     })
}

如您所见,我添加了额外的 OAuth 2.0 作用域,我们希望从 auth 提供程序请求这些作用域。要添加作用域,请调用 addthescope。我们也可以用firebase.auth().languageCode = 'pt'定义语言代码;。如果我们想在请求中发送一个特定的自定义参数,我们可以调用setCustomParamter()方法。考虑这个例子:

provider.setCustomParameters({
 'login_hint': 'admin'
});

因此,一旦您单击“使用谷歌登录”按钮,它将触发弹出窗口以通过谷歌验证:

因此,如果您已经登录,并尝试使用相同的电子邮件 ID 与不同的提供商登录,则会抛出错误,如图所示:

好的,现在让我们看看如何处理这些类型的错误。

处理帐户存在错误

考虑到在 FialBasic 设置中,我们已经启用了每个电子邮件地址的“一个帐户”选项。正如您在前面的屏幕截图中所看到的,当我们试图使用 firebase 中已存在的另一个提供商(如 Facebook)的电子邮件登录提供商(谷歌)时,它抛出了前面的屏幕截图中提到的错误-auth/account-exists-with-different-credential。要处理此错误并完成登录到所选提供商,用户必须首先登录到现有的提供商(Facebook),然后链接到以前的 AuthCredential(使用 Google ID 令牌)。重写authWithFacebook()方法后,我们的代码是这样的:

if (error.code === 'auth/account-exists-with-different-credential') {
 // Step 2.
 var pendingCred = error.credential;
 // The provider account's email address.
 var email = error.email;
 // Get registered providers for this email.
 firebaseApp.auth().fetchProvidersForEmail(email).then(function(providers) {
 // Step 3.
 // If the user has several providers,
 // the first provider in the list will be the "recommended" provider to use.
 if (providers[0] === 'password') {
 // Asks the user his password.
 // In real scenario, you should handle this asynchronously.
 var password = promptUserForPassword(); // TODO: implement promptUserForPassword to open the dialog to get the user entered password.
 firebaseApp.auth().signInWithEmailAndPassword(email, password).then(function(user) {
 // Step 4.
 return user.link(pendingCred);
 }).then(function() {
 // Google account successfully linked to the existing Firebase user.
 });
 }
 })}

有关错误代码列表的更多信息,请访问https://firebase.google.com/docs/reference/js/firebase.auth.Auth#signInWithPopup

跨刷新管理登录

现在,每次我们刷新页面时,应用程序都会忘记用户已经登录。但是,Firebase 有一个事件监听器-onAuthStateChange(),它可以在每次加载应用程序时实际检查认证状态是否更改,以及用户在上次访问应用程序时是否已经签名。如果这是真的,那么您可以自动将其重新登录。

我们将在app.js中的componentDidMount()中编写这个方法,只需看下面的代码:

 componentWillMount() {
   this.removeAuthListener = firebase.auth().onAuthStateChanged((user) 
   =>{
    if(user){
     console.log("App user data",user);
     this.setState({
       authenticated:true,
       data:user.providerData
     })
  }
 else{
   this.setState({
     authenticated:false,
     data:''
 })}
 })}

此外,在componentWillUnmount()中,我们将删除该侦听器以避免内存泄漏:

 componentWillUnmount(){
   this.removeAuthListener();
 }

现在,如果刷新浏览器,则不会影响应用程序的状态;如果您已经登录,它将保持不变。

在使用 FacebookAPI 或任何其他工具登录后,我们需要在 UI 中显示用户信息。为此,如果您再次查看路由组件,我们将使用userInfo道具将此用户信息发送到Home组件:

<Route path="/" render={() => (<Home userInfo = {this.state.data} />)} />

Home组件的渲染方法中,我们将迭代保存成功登录系统的用户数据的userInfo道具:

render() {
 var userPhoto = {width:"80px",height:"80px",margintop:"10px"}; 
 return (
 <div>
 {
 this.props.userInfo.map((profile)=> {
 return (
 <React.Fragment key={profile.uid}>
 <h2>{ profile.displayName } - Welcome to Helpdesk Application</h2>
 <div style={userPhoto}>
 <img src = { profile.photoURL } alt="user"/>
 <br/>
 <span><b>Eamil:</b></span> {profile.email }
 </div>
 </React.Fragment>
 )})
 }
 </div>
 )}

Logout()方法中,我们将简单地从 firebase auth 调用signOut()方法;通过使用 Promise API,我们将用户数据从应用程序的状态中删除。当this.state.data现在等于 null 时,用户将看到登录链接而不是注销按钮。应该是这样的:

constructor() {
 super();
  this.state = {
    redirect: false,
    data:''
  }
 }
 componentWillMount(){
   firebaseApp.auth().signOut().then((user)=>{
     this.setState({
      redirect:true,
      data: null
   })
 })}
 render() {
 if(this.state.redirect === true){
 return <Redirect to = "/" />
 }
 return (
 <div style={{textAlign:"center",position:"absolute",top:"25%",left:"50%"}}>
 <h4>Logging out...</h4>
 </div>);
 }

使用电子邮件和密码进行认证

在 Firebase 中,我们还可以将您自己的认证系统与 Firebase 认证集成,以允许用户访问数据,而无需强迫他们使用现有系统的第三方 API 创建帐户。Firebase 还允许匿名认证会话,这通常用于在等待客户端使用永久auth方法进行认证时保存少量数据。我们可以将此匿名会话配置为最后几天、几周、几个月甚至几年,直到用户使用永久login方法登录或清除其浏览器缓存。例如,购物车应用程序可以为在购物时向购物车添加内容的每个用户创建匿名认证会话。购物车应用程序将提示用户创建用于结帐的帐户;此时,购物车将被持久保存到新用户的帐户,匿名会话将被销毁。

受支持的认证状态持久性类型

我们可以根据您的应用程序或用户要求,在指定的 firebase 认证instance(.auth())上使用 firebase 中可用的三种持久性类型之一:

| 授权实例 | | 说明 | | firebase.auth.Auth.Persistence.LOCAL | “本地” | 它表示即使关闭浏览器窗口或在 React Native 中销毁活动,状态仍将保持不变。为此,需要显式注销以清除该状态。 | | firebase.auth.Auth.Persistence.SESSION | “会议” | 在这种情况下,该状态将仅持续到当前会话或选项卡,并在用户已通过认证的选项卡或窗口关闭时清除。 | | firebase.auth.Auth.Persistence.NONE | “没有” | 当我们指定它时,这意味着状态将只存储在内存中,并且在刷新窗口或应用程序时将被清除。 |

考虑这个例子:

firebaseApp.auth().setPersistence('session')
 .then(function() {
 // Auth state is now persisted in the current
 // session only. If user directly close the browser window without doing signout then it clear the existing state
 // ...
 // New sign-in will be persisted with session.
 return firebase.auth().signInWithEmailAndPassword(email, password);
 })
 .catch(function(error) {
 // Handle Errors here.
 });

我们创建一个名为authWithEmailPassword()的函数,并添加以下代码:

const email = this.emailField.value
const password = this.passwordField.value;
firebaseApp.auth().fetchProvidersForEmail(email).then((provider)=>{
 if(provider.length === 0){
 //Creating a new user
 return firebaseApp.auth().createUserWithEmailAndPassword(email,password);
 } else if(provider.indexOf("password") === -1){
 this.loginForm.reset();
 ToastDanger('Wrong Password. Please try again!!')
 } else {
 //signin user
 return firebaseApp.auth().signInWithEmailAndPassword(email,password);
 }}).then((user) => {
 if(user && user.email){
 this.loginForm.reset();
 this.setState({redirect: true});
 }})
 .catch((error)=>{
 console.log(error);
 ToastDanger(error.message);
 })

在前面的代码中,首先,我们从表单中获取值。当用户点击提交按钮时,在fetchProvidersForEmail(email)的帮助下,我们正在验证该电子邮件是否存在于我们当前的 firebase 系统中;如果没有,它将使用createUserWithEmailAndPassword()方法创建一个新用户。如果返回 true,则验证密码;如果用户输入了错误的密码,它将提示用户输入错误的密码,否则使用相同的方法登录-signInWithEmailAndPassword()-我们将通过重定向 true 更新组件的状态。

createUserWithEmailAndPassword()方法中创建新用户时,返回以下错误代码:

  • 认证/电子邮件已在使用中
  • 验证/无效电子邮件
  • 不允许认证/操作(如果 Firebase 控制台中未启用电子邮件/密码帐户。)
  • 验证/弱密码(如果密码不够强。)

当我们根据带有fetchProvidersForEmail(email)的电子邮件获取提供商时,它返回以下错误代码:

  • 验证/无效电子邮件(如果用户输入了无效电子邮件)

要阅读更多验证方法和错误代码列表,请参阅https://firebase.google.com/docs/reference/js/firebase.auth.Auth

我们还可以在应用程序中使用以下 firebase 方法来操纵用户:

var currentUser = firebase.auth().currentUser;
currentUser.updateProfile({
 displayName: “Harmeet Singh”,
 photoURL: “http://www.liferayui.com/g/200/300"
});
currentUser.sendPasswordResetEmail(“harmeetsingh090@gmail.com”); // Sends a temporary password
// Re-authentication is necessary for email, password and delete functions
var credential = firebase.auth.EmailAuthProvider.credential(email, password);
currentUser.reauthenticate(credential);
currentUser.updateEmail(“harmeetsingh090@gmail.com”);
currentUser.updatePassword(“D@#Log123”);
currentUser.delete();

成功登录后,我们将被重定向到应用程序仪表板页面,我们将能够看到完整的导航,在那里我们可以添加和查看票据:

现在,如果您单击注销按钮,将不会发生任何事情,因为我们尚未创建任何logout组件。所以在注销按钮中,我们需要做的只是调用 firebase 的signOut()方法:

class Logout extends Component {
 constructor(props) {
 super();
  this.state = {
    redirect: props.authenticated,
    data:''
 }}
 componentWillMount(){
  firebaseApp.auth().signOut().then((user)=>{
    this.setState({
       redirect:true,
       data: null
   })
 })}
 render() {
 if(this.state.redirect === true){
    return <Redirect to = "/" />
 }
 return (
 <div style={{textAlign:"center",position:"absolute",top:"25%",left:"50%"}}>
   <h4>Logging out...</h4>
 </div>
 );
 }}

在前面的代码中,我们创建了一个组件,并根据组件 props(authenticated)中传递的值设置状态;然后,在组件生命周期钩子方法componentWillMount()中,我们调用了firebaseApp.auth().signout()方法,用于注销用户,将其重定向到登录页面,并从状态中删除数据。

总结

在本章中,我们了解了如何借助 firebase 认证系统使我们的应用程序免受未知用户的攻击。我们还了解了如何在节点环境中配置 React-Firebase 应用程序,以及如何在 React 中创建登录表单,并在 React 中集成 Firebase 认证登录方法,例如 Google、Facebook 和电子邮件/密码。类似地,我们可以在应用程序中集成其他认证登录方法。

我们还介绍了如何根据 firebase 认证错误代码处理认证错误,这些错误代码有助于我们在应用程序中执行操作。对于Persist认证状态,我们可以使用firebaseApp.auth().setPersistence('session'),该方法允许我们维护 firebase 认证状态。

在下一章中,我们将探索 Redux 的威力,并使用 React、Redux 和 Firebase 创建一个实时订票应用程序。