Javascript 使用ReactJS和Firebase进行身份验证

Javascript 使用ReactJS和Firebase进行身份验证,javascript,reactjs,firebase,authentication,firebase-authentication,Javascript,Reactjs,Firebase,Authentication,Firebase Authentication,我刚接触web开发,开始学习ReactJS 到目前为止,构建简单的web应用程序没有问题 现在我想使用Firebase进行身份验证 我知道如何使用Firebase对用户进行身份验证,但我不知道如何设计前端来限制对某些页面的访问 之前,我使用了PHP,其中我使用了session变量和include来包含要显示给用户的HTML部分 但我不知道如何使用Firebase在ReactJS中实现这一点 初始和失败的进近: import React from 'react'; import ReactDOM

我刚接触web开发,开始学习ReactJS

到目前为止,构建简单的web应用程序没有问题

现在我想使用Firebase进行身份验证

我知道如何使用Firebase对用户进行身份验证,但我不知道如何设计前端来限制对某些页面的访问

之前,我使用了PHP,其中我使用了
session
变量和
include
来包含要显示给用户的HTML部分

但我不知道如何使用Firebase在ReactJS中实现这一点

初始和失败的进近:

import React from 'react';
import ReactDOM from 'react-dom';
import Login from './components/Login/Login';
import Home from './components/Home/Home';
import fire from './components/Fire';


class App extends React.Component {

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

        this.authListener = this.authListener.bind(this);

    }

    componentDidMount() {
        this.authListener();
    }

    authListener() {
        fire.auth().onAuthStateChanged(user => {
            if (user) {
              // User is signed in.
                console.log(user);
                this.setState({
                    loggedIn: true
                })
            } else {
              // No user is signed in.
                this.setState({
                    loggedIn: false
                });
            }
        });

    }

    render() {

        return (
            <div>
                {this.state.loggedIn ? <Home/> : <Login/>}
            </div>
        );
    }
}

ReactDOM.render(
    <App/>, document.getElementById('app'));
fire
    .auth()
    .signInWithEmailAndPassword(this.state.email, this.state.password)
    .catch(function (error) {
          // Handle Errors here.
          var errorCode = error.code;
          var errorMessage = error.message;
          console.log(error);
          // ...
     });
我想更新
this.state.loggedIn
并用它来显示组件。但这不是一种正确的方式,因为我将两个组件都发送到显示器上,我们可以使用Chrome中的React developer extension轻松地更改组件的状态

这是我的主index.js代码:

import React from 'react';
import ReactDOM from 'react-dom';
import Login from './components/Login/Login';
import Home from './components/Home/Home';
import fire from './components/Fire';


class App extends React.Component {

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

        this.authListener = this.authListener.bind(this);

    }

    componentDidMount() {
        this.authListener();
    }

    authListener() {
        fire.auth().onAuthStateChanged(user => {
            if (user) {
              // User is signed in.
                console.log(user);
                this.setState({
                    loggedIn: true
                })
            } else {
              // No user is signed in.
                this.setState({
                    loggedIn: false
                });
            }
        });

    }

    render() {

        return (
            <div>
                {this.state.loggedIn ? <Home/> : <Login/>}
            </div>
        );
    }
}

ReactDOM.render(
    <App/>, document.getElementById('app'));
fire
    .auth()
    .signInWithEmailAndPassword(this.state.email, this.state.password)
    .catch(function (error) {
          // Handle Errors here.
          var errorCode = error.code;
          var errorMessage = error.message;
          console.log(error);
          // ...
     });
身份验证工作正常,我可以在控制台日志中看到它

那么,我应该如何在ReactJS+Firebase中进行身份验证?(是否可以不使用任何其他包,如react-routes等?)

或者我应该为此使用云函数吗

在此之前,我使用了PHP,其中我使用了session变量和include来包含要向用户显示的HTML部分

Firebase有多种方式保持其身份验证状态,如下所述:

默认情况下,它是
local
。在Web上,这是
localStorage
。这对您来说可能是一个巨大的变化,因为通常身份验证状态是在服务器端和客户端完成的某种会话或cookie中

那么,我应该如何在ReactJS+Firebase中进行身份验证?(是否可以不使用任何其他包,如react-routes等?)

但使用Firebase,一切都是在客户端完成的。用户成功进行身份验证后,您将有权访问其身份验证令牌,如下所述:

使用此令牌,您需要在服务器端进行如下验证:以保护/保护任何API访问

但是为了保护React应用程序中的某些页面,您需要在某种中间件中验证
localStorage
中的身份验证状态。最好在React生命周期方法之一中有一个身份验证状态的侦听器:


在应用程序中的任何时候,身份验证状态都将变为无效,请阻止他们查看页面。

好的,我将向您展示如何在React应用程序上使用firebase auth。我只是想让你知道这不是正确的方法,你会找到很多方法

让我们开始吧,首先我使用Google Auth,我有一个名为
firebase.service.js
的文件,在这里我处理Auth。该文件看起来像:

import firebase from 'firebase';

import { firebaseConfig } from './private';


export const firebaseApp = firebase.initializeApp(firebaseConfig);

export const auth = firebase.auth();
export const db = firebase.database();

export function loginGoogle(/* options */) {
  const provider = new firebase.auth.GoogleAuthProvider();

  return firebase.auth().signInWithPopup(provider);
}
import React from 'react';
import ReactDOM from 'react-dom';
import firebase from 'firebase';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';

import { auth } from './services';

auth.setPersistence(firebase.auth.Auth.Persistence.LOCAL).then(() => {
  const stop = auth.onAuthStateChanged(() => {
    ReactDOM.render(<App />, document.getElementById('root'));
    stop();
  });
});

registerServiceWorker();
firebaseConfig
对象如下所示:

const firebaseConfig = {
    apiKey: API_KEY,
    authDomain: AUTH_DOMAIN,
    databaseURL: DB_URL,
    projectId: PROJECT_ID,
    storageBucket: STORE_BUCKET,
    messagingSenderId: MSG_SENDER,
};
您可以在Firebase控制台上找到它

在安装该应用程序的索引文件处,我使用身份验证检查包装了
ReactDOM.render
方法,以确保用户是否登录。该索引如下所示:

import firebase from 'firebase';

import { firebaseConfig } from './private';


export const firebaseApp = firebase.initializeApp(firebaseConfig);

export const auth = firebase.auth();
export const db = firebase.database();

export function loginGoogle(/* options */) {
  const provider = new firebase.auth.GoogleAuthProvider();

  return firebase.auth().signInWithPopup(provider);
}
import React from 'react';
import ReactDOM from 'react-dom';
import firebase from 'firebase';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';

import { auth } from './services';

auth.setPersistence(firebase.auth.Auth.Persistence.LOCAL).then(() => {
  const stop = auth.onAuthStateChanged(() => {
    ReactDOM.render(<App />, document.getElementById('root'));
    stop();
  });
});

registerServiceWorker();
在这里,您可以看到该函数检查是否存在任何已登录的用户,否则它会将用户发送回根路径。请注意,我正在从
/services
导入
auth
,而不是从
firebase
导入,这是因为此auth是在
firebase.service.js
处初始化的,然后我通过所有应用程序使用它

现在您可以将此
PrivateRoute
用作公共路由,区别在于将检查用户是否已登录。以此为例:

import * as React from 'react';
import { BrowserRouter, Route, Switch, Redirect } from 'react-router-dom';
import { Layout } from 'antd';
import moment from 'moment';

import 'moment/locale/pt-br';
import 'antd/dist/antd.css';

import { PrivateRoute, MainLogged, Login, Navbar, Page404 } from './components';

const { Header } = Layout;

moment.locale('pt-br');

function Main() {
  return <Redirect to="/login" />;
}

function App() {
  return (
    <BrowserRouter>
      <Layout>
        <Header style={{ paddingLeft: '0', backgroundColor: '#096dd9' }}>
          <Navbar />
        </Header>
        <Switch>
          <Route exact path="/" component={Main} />
          <Route exact path="/login" component={Login} />
          <PrivateRoute path="/app" component={MainLogged} />
          <Route component={Page404} />
        </Switch>
      </Layout>
    </BrowserRouter>
  );
}

export default App;
import*as React from'React';
从“react router dom”导入{BrowserRouter,Route,Switch,Redirect};
从“antd”导入{Layout};
从“力矩”中导入力矩;
导入“时刻/地点/pt br”;
导入“antd/dist/antd.css”;
从“/components”导入{PrivateRoute,MainLogged,Login,Navbar,Page404};
const{Header}=布局;
地点(“pt-br”);
函数Main(){
返回;
}
函数App(){
返回(
);
}
导出默认应用程序;
如您所见,
PrivateRouse
react路由器的
Route
组件并排使用


我想这就是全部,如果你想问任何其他问题,请发表评论,如果你想看看我从哪里获取这些代码的项目,你可以找到它。

更新:

import React from 'react';
import ReactDOM from 'react-dom';
import Login from './components/Login/Login';
import Home from './components/Home/Home';
import fire from './components/Fire';


class App extends React.Component {

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

        this.authListener = this.authListener.bind(this);

    }

    componentDidMount() {
        this.authListener();
    }

    authListener() {
        fire.auth().onAuthStateChanged(user => {
            if (user) {
              // User is signed in.
                console.log(user);
                this.setState({
                    loggedIn: true
                })
            } else {
              // No user is signed in.
                this.setState({
                    loggedIn: false
                });
            }
        });

    }

    render() {

        return (
            <div>
                {this.state.loggedIn ? <Home/> : <Login/>}
            </div>
        );
    }
}

ReactDOM.render(
    <App/>, document.getElementById('app'));
fire
    .auth()
    .signInWithEmailAndPassword(this.state.email, this.state.password)
    .catch(function (error) {
          // Handle Errors here.
          var errorCode = error.code;
          var errorMessage = error.message;
          console.log(error);
          // ...
     });
html文件中链接的所有内容都应该始终来自公共目录。因此,将捆绑的
.js
文件保存在公共目录中

我为初学者写了一些节省时间的小贴士。你可以找到更多关于初学者的提示


其实很简单

如果只想将所需的html文件发送到浏览器,则每次需要完全不同的html时,都必须点击服务器

你说你用的是PHP。在PHP中,我们使用会话来了解一个人是否登录

所以,我们尝试在这里实现它

首先让我们看看PHP中的会话是如何工作的。摘自

在一般情况下:

  • 会话id在用户创建会话时发送给用户
  • 它存储在cookie中(默认情况下称为
    PHPSESSID
  • 浏览器会将cookie随每个请求一起发送到服务器
  • 服务器(PHP)使用包含会话id的cookie来知道哪个文件对应于该用户
会话文件中的数据是会话的内容, 序列化(即,表示为字符串--使用函数,如 ) ; 并在加载文件时取消序列化 PHP,以填充
$\u会话
数组


有时,会话id不存储在cookie中,而是发送进来 URL也是——但这很少见,n