javascript - 使用 ReactJS 和 Firebase 进行身份验证
问题描述
我是 Web 开发新手,开始学习 ReactJS。
到目前为止,构建简单的 Web 应用程序没有问题。
现在我想使用 Firebase 进行身份验证。
我知道如何使用 Firebase 对用户进行身份验证,但我无法了解如何设计前端来限制对某些页面的访问。
以前,我使用 PHP,因为我使用session
变量并include
包含 HTML 的部分以向用户显示。
但我不知道如何使用 Firebase 在 ReactJS 中做到这一点。
初始和失败的方法:
我想更新this.state.loggedIn
并使用它来显示组件。但这不是正确的方法,因为我将两个组件都发送给显示,并且我们可以使用 Chrome 中的 React 开发人员扩展轻松更改组件的状态。
这是我的主要 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'));
在 Login.js 中,我调用了 Firebase 身份验证函数。
只是片段:
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 等?)
或者我应该为此使用云功能吗?
解决方案
更新:
您在 html 文件中链接的所有内容都应始终来自您的公共目录。因此,请将您的捆绑.js
文件保存在您的公共目录中。
我已经为初学者写了一些节省时间的技巧。您可以在此处找到有关初学者提示的更多信息。
其实很简单。
如果您只想将所需的 html 文件发送到浏览器,则每次需要完全不同的 html 时都必须访问服务器。
你说你用过PHP。在 PHP 中,我们使用会话来了解一个人是否已登录。
所以,我们尝试在这里实现它。
首先让我们看看 PHP 中的会话是如何工作的。取自一个SO 答案
一般情况下:
- 创建会话时将会话 ID 发送给用户。
- 它存储在 cookie 中(默认情况下称为
PHPSESSID
)- 该 cookie 由浏览器随每个请求发送到服务器
- 服务器 (PHP) 使用包含 session_id 的 cookie 来了解哪个文件对应于该用户。
会话文件中的数据是
$_SESSION
, 序列化的内容(即,表示为字符串 - 使用诸如 serialize之类的函数);并且在 PHP 加载文件时取消序列化,以填充$_SESSION
数组。
有时,会话 ID 不存储在 cookie 中,而是在 URL 中发送——但现在这种情况很少见。
有关更多信息,您可以查看手册的会话处理部分,其中提供了一些有用的信息。例如,有一个关于Passing the Session ID的页面,它解释了会话 id 如何在页面之间传递,使用 cookie 或在 URL 中 - 以及哪些配置选项会影响这一点。
所以,session
只是一个cookie。然后我想我们可以使用 cookie 来了解用户登录状态。
在 Firebase 中,cookie 存在问题。您只能将 cookie 名称设置为__session
. Firebase 会忽略其他名称,因此您无法读取服务器上的 cookie。
您需要使用 Firebase Functions 来做一些后端工作并根据用户登录状态提供 html。
因此,在您的项目目录中设置 Firebase 函数。在根中,
$ firebase init functions
现在您必须对 Firebase 说,任何进入您的域的请求都必须调用一个函数。
为此,您必须rewrites
在firebase.json
文件中写入。我们的函数名称将是main
.
{
"database": {
"rules": "database.rules.json"
},
"hosting": {
"public": "/dev",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites":[{
"source": "**",
"function": "main"
}]
}
}
现在创建一个index.js
anywhere(首选项目目录的根目录,因为这是主文件)。
index.js
import express from 'express';
import * as functions from 'firebase-functions';
import fs from 'fs';
var cookieParser = require('cookie-parser')
const app = express();
app.use(cookieParser());
app.get('**', (req, res) => {
// Check the custom set cookie for user
// If the user is not logged-in, redirect to Login. Otherwise, redirect to Home page
if (req.cookies.__session == 'loggedin') {
var index = fs.readFileSync(__dirname + '/src/Home/index.html', 'utf8');
}
else {
var index = fs.readFileSync(__dirname + '/src/Login/index.html', 'utf8');
}
res.send(index);
});
export let main = functions.https.onRequest(app);
关于以上部分的一些解释:
express
:用于处理请求并发送响应。firebase-functions
: 由 Google 提供,用于使用 Firebase Functions。fs
:我们根据用户登录状态从文件系统中读取相应的html并提供。cookie-parser
: 我们使用它来轻松访问我们的 cookie。
注意:您需要将其转换为 ES5。所以使用 babel 命令来转换它(我假设你保存index.js
在你的根目录中。)
$ babel index.js -d functions
我们使用 cookie 命名__session
来了解用户登录状态。
如果__session
设置为loggedin
,我们发送用户Home
html
。否则,我们发送Login
html
.
现在,真正的问题是:“我们需要在哪里设置 cookie __session
?”
我们在用户浏览器中设置 cookie。
我们利用onAuthStateChanged()
.
Login page component
用你喜欢的方式调用这个方法:
componentDidMount() {
this.authListener();
}
authListener() {
fire.auth().onAuthStateChanged(user => {
if (user) {
// User is signed in.
if (Cookies.get('__session') === undefined) {
Cookies.set('__session', 'loggedin', { expires: 3652 });
window.location.reload();
}
} else {
// No user is signed in.
Cookies.remove('__session');
}
});
}
注意:Cookies
对象是从js-cookie导入的。所以,安装它。
我们在这里做的是:
首先,
onAuthStateChanged()
在页面加载时最初调用。如果用户已经登录,我们进入
if
块。然后我们检查
__session
cookie。这很重要,因为有时用户可以清除所有 cookie。当我们尝试读取服务器中的 cookie 时,我们得到undefined
并将登录页面发送给用户。过程从 重复1
。然后我们重新加载页面。当我们重新加载页面时,用户再次点击服务器。然后我们可以检查
__session
cookie 并将其发送Home
html
给用户。
推荐阅读
- html - 如何围绕图像和图标制作 div 页面(Bootstrap 4)
- elasticsearch - 如何在elasticsearch中搜索数组的多个字段
- javascript - JavaScript 代理在“get”上返回异步值
- java - 如何从片段内的视图持有者调用函数
- reactjs - 反应路由器重定向覆盖其他路由器组件
- python-3.x - Linux CentOS 8 - Pip3 安装 Mariadb
- wix - 通过我的 wix 安装程序安装 rabbitmq 并创建新用户和主机失败
- linear-programming - 最大化比率/百分比
- docker - echo 告诉我我的环境变量已定义,但 docker-compose 告诉我“未设置变量”。如何将它们传递给 docker-compose?
- google-tag-manager - Google 跟踪代码管理器标记触发但未显示在页面上