react-native-firebase 登录功能集成与实现

以下内容基于 react-native-firebase 版本4.1

常用api:
//匿名登录:
    firebase.auth().signInAnonymously()
            .then(() => {
                this.setState({
                    isAuthenticated: true,
                });
            });

 /**
     * 手机号码登录
     * @returns {Promise<void>}
     * @private
     */
    _loginWithPhone = async () => {
        console.log('手机登录');
        try {
            const ConfirmationResult = await firebase.auth().signInWithPhoneNumber('+86' + this.state.username);
            console.log(ConfirmationResult);

            //以下内容是校验验证码是否正确,123456是我们默认的验证码
            //校验成功就登录了,应该写在两个方法中依次触发
            try {
                let user = await ConfirmationResult.confirm('123456');
                console.log(user)
            } catch (e) {
                console.log(e)
            }

        } catch (e) {
            console.log(e)
        }

    };

    /**
     * 邮箱登录
     * @returns {Promise<void>}
     * @private
     */
    _loginWithEmail = async () => {
        console.log('邮箱登录');
        try {
            let loginResult = await firebase.auth().signInAndRetrieveDataWithEmailAndPassword(this.state.username, this.state.password);
            console.log(loginResult)
        } catch (e) {
            console.log(e);
            alert('账户信息错误')
        }
    };
/**
     * 根据输入内容判断是邮箱还是手机号
     * 其实应该分别用两个不同控件实现
     * 因为邮箱是直接输入账号和密码
     * 手机号的话要发送并等待验证码
     */
    _login = () => {
        let {username} = this.state;
        let emailReg = /\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/;
        let phoneReg = /^[1][0-9]{10}$/;

        console.log(`start login:${this.state.username}, ${this.state.password}`);

        if (emailReg.test(username)) {
            this._loginWithEmail()
        } else if (phoneReg.test(username)) {
            this._loginWithPhone()
        } else {
            alert('请输入正确的邮箱或电话')
        }
    };    

//查看登录用户信息
 console.log(firebase.auth().currentUser)

//退出登录
firebase.auth().signOut()

//监听登录状态
    this.unsubscribe = firebase.auth().onAuthStateChanged((user) => {
      if (user) {
        this.setState({ user: user.toJSON() });
      } else {
        // 用户已退出,重置状态
        this.setState({
          user: null,
          message: '',
          codeInput: '',
          phoneNumber: '+44',
          confirmResult: null,
        });
      }
    });

安装

iOS安装

首先确保您已遵循。初始设置指南

Add the pod

将以下内容添加到您的Podfile:

pod 'Firebase/Auth'

run pod update。

如果您打算使用电子邮件登录链接,那么您还需要遵循。iOS动态链接安装指南

Android安装

添加依赖项

将Firebase身份验证依赖项添加到android/app/build.gradle:

dependencies {
  // ...
  implementation "com.google.firebase:firebase-auth:15.1.0"
}

如果您打算使用电子邮件登录链接,则还需要遵循Android的动态链接安装指南

安装RNFirebase身份验证包

添加RNFirebaseAuthPackage到您的android/app/src/main/java/com/[app name]/MainApplication.java:

// ...
import io.invertase.firebase.RNFirebasePackage;
import io.invertase.firebase.auth.RNFirebaseAuthPackage; // <-- Add this line

public class MainApplication extends Application implements ReactApplication {
    // ...

    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
          new RNFirebasePackage(),
          new RNFirebaseAuthPackage() // <-- Add this line
      );
    }
  };
  // ...
}

身份验证 - 入门

无论您是在寻找匿名,电子邮件和密码还是社交身份验证,Firebase都可让您轻松实现身份验证。

对于新手来说,虽然API很简单,但实际上将其应用到应用程序的流程中可能看起来很棘手。以下指南将介绍您可能会遇到的几种情况。

我们只会在这里使用React Native和RNFirebase以避免任何混淆,尽管您可能希望将其与Redux等状态管理工具联系起来,因为您的应用程序变得更加复杂。

RNFirebase使用本机Firebase SDK,因此您的身份验证状态将保存到设备,这意味着如果您关闭应用程序并重新打开应用程序,则用户无需重新进行身份验证。

匿名认证

即使你的应用程序可能没有任何必要的身份验证,如果你能以某种方式跟踪你的用户,给他们一个唯一的标识符,这不是很好吗?

这正是匿名身份验证所做的事情。它为用户创建帐户,而无需进行身份验证。

确保您已在身份验证下Anonymous的Firebase控制台上启用了登录!
开启登录

匿名登录方法:

import firebase from 'react-native-firebase';
...
    /**
     * 匿名登录
     * @private
     */
    _anonymousLogin = () => {
        firebase.auth().signInAnonymously()
            .then(() => {
                this.setState({
                    isAuthenticated: true,
                });
            });
    }
...

render(){
<Text onPress={this._anonymousLogin}>{`匿名登录:${this.state.isAuthenticated}`}</Text>
    )
}

在显示应用程序之前匿名验证用户身份。我们将使用auth#signInAnonymously方法来执行此操作::

import React from 'react';
import { View, Text } from 'react-native';
import firebase from 'react-native-firebase';

class App extends React.Component {

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

  componentDidMount() {
    firebase.auth().signInAnonymously()
      .then(() => {
        this.setState({
          isAuthenticated: true,
        });
      });
  }

  render() {
    // If the user has not authenticated
    if (!this.state.isAuthenticated) {
      return null;
    }

    return (
      <View>
        <Text>Welcome to my awesome app!</Text>
      </View>
    );
  }

}

export default App;

现在应用程序将不会呈现内容,直到auth#signInAnonymously方法已解决。您现在可以使用auth#currentUser属性访问匿名用户详细信息。

<Text onPress={() => {
                        console.log(firebase.auth().currentUser)
                    }}>查看匿名登录信息</Text>

如果用户关闭并重新打开应用,Firebase会自动将其重新登录到已分配的匿名帐户(如果可用)。例如将登录方法写入componentDidMount

必需的电子邮件/密码验证

另一种常见情况是要求用户在可以访问您的应用之前登录帐户。您可能也希望他们也可以注销。

幸运的是,通过提供auth#signInWithEmailAndPassword方法,Firebase使这一切变得非常简单。如果您还需要注册屏幕,请改用auth#createUserWithEmailAndPassword。
请改用 signInAndRetrieveDataWithEmailAndPassword
确保您已在身份验证下Email/Password的Firebase控制台上启用了登录!

与匿名身份验证非常相似,我们需要使用状态根据当前的Firebase身份验证状态呈现应用。
主要区别在于我们需要跟踪用户当前的身份验证状态(用于登录,创建帐户或注销)。这可以使用auth#onAuthStateChanged方法完成:

我们还将跟踪应用程序卸载时的取消订阅者功能。
Login.js

        /**
     * 邮箱登录
     * @returns {Promise<void>}
     * @private
     */
    _loginWithEmail = async () => {
        try {
            let a = await firebase.auth().signInAndRetrieveDataWithEmailAndPassword('zhuoyuan93@gmail.com', 'password');
            console.log(a)
        } catch (e) {
            console.log(e);
            alert("密码错误")
        }

    }

    render() {
        return (
            <View>
                <Text onPress={this._loginWithEmail}>
                    LOGIN页面
                </Text>

            </View>
        );
    }

登录成功之后会自动刷新页面。
我在方法中直接写了参数(邮件地址和密码),实际开发中可以有邮件和密码输入框,然后登录按钮调用方法firebase.auth().signInAndRetrieveDataWithEmailAndPassword(email,password)
因为我密码是不对的,所以会走catch的内容,如果是正确的密码,则会打印出带有登录的user消息的内容并在短暂延迟后刷新页面。

import React from 'react';
import { View, Text } from 'react-native';
import firebase from 'react-native-firebase';

import Login from './screens/Login';

class App extends React.Component {

  constructor() {
    super();
    this.unsubscriber = null;
    this.state = {
      user: null,
    };
  }

  /**
   * Listen for any auth state changes and update component state
   */
  componentDidMount() {
    this.unsubscriber = firebase.auth().onAuthStateChanged((user) => {
      this.setState({ user });
    });
  }

  componentWillUnmount() {
    if (this.unsubscriber) {
      this.unsubscriber();
    }
  }

  render() {
    if (!this.state.user) {
      return <Login />;
    }

    return (
      <View>
        <Text>Welcome to my awesome app {this.state.user.email}!</Text>
      </View>
    );
  }

}

当onAuthStateChanged监听器返回用户或者null,我们可以直接将其传递给我们的状态。

发生身份验证事件时,将使用我们的用户(已登录或创建帐户)或null(已注销)更新用户状态。如果用户状态为null,则显示登录屏幕。

电话验证

RNFirebase提供了两种使用电话号码与用户签名的方法; auth#signInWithPhoneNumber和auth#verifyPhoneNumber。两者都提供了不同的工作流程,可以最好地将其与您的应 signInWithPhoneNumber一旦用户确认了他们的电话号码,他们将自动签署用户,同时verifyPhoneNumber将提供有关当前验证状态的反馈,但要求您在确认后手动签署用户。

signInWithPhoneNumber

signInWithPhoneNumber 是处理auth流程的更直接的实现,但是它提供了较少的灵活性来处理可能发生的各种情况。

1.触发电话验证

try {
            const ConfirmationResult = await firebase.auth().signInWithPhoneNumber('+86' + this.state.username);
            console.log(ConfirmationResult);
        } catch (e) {
            console.log(e)
        }

返回结果:

2.确认验证码

try {
                let user = await ConfirmationResult.confirm('123456');
                console.log(user)
            } catch (e) {
                console.log(e)
            }

验证成功打印的结果:
这里写图片描述
可以看到,验证成功之后会返回user的数据,RNFirebase会保存起来。
之后可以通过firebase.auth().currentUser拿到user的相关信息

在iOS上,这就是所需要的。

但是,如果Google Play服务可以自动检测传入的消息(并且不显示它!),Android也会提供“自动验证”。

3. [Android]处理自动验证

要处理自动验证,我们需要监听auth#onAuthStateChanged:

 this.unsubscriber = firebase.auth().onAuthStateChanged((user) => {
  // 用户已经通过验证并已登录
            this.setState({user});
        });

这个是监听是否登录的,可以写在componentDidMount中,记得卸载。
以下是官方给的完整例子,我加了一些注释:

import React, { Component } from 'react';
import { View, Button, Text, TextInput, Image } from 'react-native';

import firebase from 'react-native-firebase';

const successImageUri = 'https://cdn.pixabay.com/photo/2015/06/09/16/12/icon-803718_1280.png';

export default class PhoneAuthTest extends Component {
  constructor(props) {
    super(props);
    this.unsubscribe = null;
    this.state = {
      user: null,
      message: '',
      codeInput: '',
      phoneNumber: '+44',
      confirmResult: null,
    };
  }

  componentDidMount() {
  //监听登录状态
    this.unsubscribe = firebase.auth().onAuthStateChanged((user) => {
      if (user) {
        this.setState({ user: user.toJSON() });
      } else {
        // 用户已退出,重置状态
        this.setState({
          user: null,
          message: '',
          codeInput: '',
          phoneNumber: '+44',
          confirmResult: null,
        });
      }
    });
  }

  componentWillUnmount() {
  //卸载组件时,卸载掉监听事件
     if (this.unsubscribe) this.unsubscribe();
  }

//发送验证码
  signIn = () => {
    const { phoneNumber } = this.state;
    this.setState({ message: 'Sending code ...' });

    firebase.auth().signInWithPhoneNumber(phoneNumber)
      .then(confirmResult => this.setState({ confirmResult, message: 'Code has been sent!' }))
      .catch(error => this.setState({ message: `Sign In With Phone Number Error: ${error.message}` }));
  };

//验证验证码是否正确
  confirmCode = () => {
    const { codeInput, confirmResult } = this.state;

    if (confirmResult && codeInput.length) {
      confirmResult.confirm(codeInput)
        .then((user) => {
          this.setState({ message: 'Code Confirmed!' });
        })
        .catch(error => this.setState({ message: `Code Confirm Error: ${error.message}` }));
    }
  };

//退出登录
  signOut = () => {
    firebase.auth().signOut();
  }

//输入手机号的组件
  renderPhoneNumberInput() {
   const { phoneNumber } = this.state;

    return (
      <View style={{ padding: 25 }}>
        <Text>Enter phone number:</Text>
        <TextInput
          autoFocus
          style={{ height: 40, marginTop: 15, marginBottom: 15 }}
          onChangeText={value => this.setState({ phoneNumber: value })}
          placeholder={'Phone number ... '}
          value={phoneNumber}
        />
        <Button title="Sign In" color="green" onPress={this.signIn} />
      </View>
    );
  }

//实时状态显示
  renderMessage() {
    const { message } = this.state;

    if (!message.length) return null;

    return (
      <Text style={{ padding: 5, backgroundColor: '#000', color: '#fff' }}>{message}</Text>
    );
  }

//验证码组件
  renderVerificationCodeInput() {
    const { codeInput } = this.state;

    return (
      <View style={{ marginTop: 25, padding: 25 }}>
        <Text>Enter verification code below:</Text>
        <TextInput
          autoFocus
          style={{ height: 40, marginTop: 15, marginBottom: 15 }}
          onChangeText={value => this.setState({ codeInput: value })}
          placeholder={'Code ... '}
          value={codeInput}
        />
        <Button title="Confirm Code" color="#841584" onPress={this.confirmCode} />
      </View>
    );
  }

  render() {
    const { user, confirmResult } = this.state;
    return (
      <View style={{ flex: 1 }}>

        {!user && !confirmResult && this.renderPhoneNumberInput()}

        {this.renderMessage()}

        {!user && confirmResult && this.renderVerificationCodeInput()}

        {user && (
          <View
            style={{
              padding: 15,
              justifyContent: 'center',
              alignItems: 'center',
              backgroundColor: '#77dd77',
              flex: 1,
            }}
          >
            <Image source={{ uri: successImageUri }} style={{ width: 100, height: 100, marginBottom: 25 }} />
            <Text style={{ fontSize: 25 }}>Signed In!</Text>
            <Text>{JSON.stringify(user)}</Text>
            <Button title="Sign Out" color="red" onPress={this.signOut} />
          </View>
        )}
      </View>
    );
  }
}

verifyPhoneNumber

此实现使您可以完全控制任一平台上的电话号码验证流程以及适合任何UI流程的灵活API,如果您使用了诸如存储,上传任务/数据库等内容,则应该熟悉使用。如果您想要将电话凭证与现有帐户相关联,而不是仅仅签署用户,则特别有用。

firebase.auth()
  .verifyPhoneNumber(phoneNumber)
  .on('state_changed', (phoneAuthSnapshot) => {
    //你如何处理这些状态事件完全取决于你的ui流程以及你是否需要同时支持ios和android。
    //简而言之:并非所有人都需要处理 - 这完全取决于你,你的ui和支持的平台。

    // E.g 你可以只在这里处理特定于Android的事件,然后让其余部分回到optionalErrorCb或optionalCompleteCb函数
    switch (phoneAuthSnapshot.state) {
      // ------------------------
      //  IOS AND ANDROID EVENTS
      // ------------------------
      case firebase.auth.PhoneAuthState.CODE_SENT: // or 'sent'
        console.log('code sent');
        // on ios this is the final phone auth state event you'd receive
        // so you'd then ask for user input of the code and build a credential from it
        // as demonstrated in the `signInWithPhoneNumber` example above
        break;
      case firebase.auth.PhoneAuthState.ERROR: // or 'error'
        console.log('verification error');
        console.log(phoneAuthSnapshot.error);
        break;

      // ---------------------
      // ANDROID ONLY EVENTS
      // ---------------------
      case firebase.auth.PhoneAuthState.AUTO_VERIFY_TIMEOUT: // or 'timeout'
        console.log('auto verify on android timed out');
        // proceed with your manual code input flow, same as you would do in
        // CODE_SENT if you were on IOS
        break;
      case firebase.auth.PhoneAuthState.AUTO_VERIFIED: // or 'verified'
        // auto verified means the code has also been automatically confirmed as correct/received
        // phoneAuthSnapshot.code will contain the auto verified sms code - no need to ask the user for input.
        console.log('auto verified on android');
        console.log(phoneAuthSnapshot);
        // Example usage if handling here and not in optionalCompleteCb:
        // const { verificationId, code } = phoneAuthSnapshot;
        // const credential = firebase.auth.PhoneAuthProvider.credential(verificationId, code);

        // Do something with your new credential, e.g.:
        // firebase.auth().signInWithCredential(credential);
        // firebase.auth().currentUser.linkWithCredential(credential);
        // etc ...
        break;
    }
  }, (error) => {
    // optionalErrorCb would be same logic as the ERROR case above,  if you've already handed
    // the ERROR case in the above observer then there's no need to handle it here
    console.log(error);
    // verificationId is attached to error if required
    console.log(error.verificationId);
  }, (phoneAuthSnapshot) => {
    // optionalCompleteCb would be same logic as the AUTO_VERIFIED/CODE_SENT switch cases above
    // depending on the platform. If you've already handled those cases in the observer then
    // there's absolutely no need to handle it here.

    // Platform specific logic:
    // - if this is on IOS then phoneAuthSnapshot.code will always be null
    // - if ANDROID auto verified the sms code then phoneAuthSnapshot.code will contain the verified sms code
    //   and there'd be no need to ask for user input of the code - proceed to credential creating logic
    // - if ANDROID auto verify timed out then phoneAuthSnapshot.code would be null, just like ios, you'd
    //   continue with user input logic.
    console.log(phoneAuthSnapshot);
  });
// optionally also supports .then & .catch instead of optionalErrorCb &
// optionalCompleteCb (with the same resulting args)
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 点我我会动 设计师:白松林 返回首页