为 React 应用程序添加用户身份验证功能
在构建网络应用程序时,用户身份验证是添加到应用程序中的必要功能。用户身份验证允许通过验证的用户访问应用程序中的可用功能,并拒绝未经验证的用户访问。
在 React 应用程序中集成用户身份验证并非易事,而且非常耗时,因为这涉及到多个复杂的过程,例如散列密码、生成和管理身份验证令牌等等。
不过,有了 Back4App 这样的平台,在 React 应用程序中集成用户身份验证就变得简单易行了。在本文中,您将了解如何使用 Back4App 在 React 应用程序中添加用户身份验证。
Contents
了解用户身份验证
用户身份验证是确定试图访问应用程序的人的身份的过程。
它要求试图访问应用程序的人提供可验证的凭证,凭证的形式可以是用户名和密码、生物识别数据、访问密钥/令牌等。
如果您的身份验证机制认为凭据有效,就会允许用户访问您的应用程序,否则就会拒绝身份验证请求并给出相应的错误信息。
常见身份验证方法
常见的身份验证方法包括以下几种:
- 用户名和密码:这种身份验证方法要求用户提供有效的用户名和密码,以验证其身份。用户提供用户名和密码后,这种身份验证机制会将其与数据库中存储的数据进行比较,只有在两者匹配时才会批准身份验证请求。
- 多因素身份验证(MFA):多因素身份验证是指结合多种身份验证机制对用户进行身份验证。在使用 MFA 的身份验证系统中,用户需要多次验证自己的身份。例如,用户在使用用户名和密码验证身份后,可能需要输入验证码。
- 生物识别身份验证:生物识别身份验证是指依靠生物特征(如脸部、虹膜图案、指纹或声音识别)来验证用户身份的身份验证机制。
- OAuthOAuth 是一种身份验证协议,允许用户通过授权应用程序访问其首选的 OAuth 提供商(如 Facebook 或 X(前 Twitter))来验证其身份。当用户尝试使用 OAuth 进行身份验证时,他们将被重定向到 OAuth 提供商的登录屏幕,以验证其身份。
- JSON 网络令牌(JWT):JWT 是一种可移植、URI 安全的紧凑型令牌格式,通常用于在不同方之间安全地传输身份验证和授权详细信息。使用 JWT 进行身份验证时,用户需要在请求中发送 JWT 访问令牌,以验证自己的身份。
使用 Back4app 为应用程序添加用户身份验证功能
Back4app是一个云平台,可提供多种服务,包括 “后台即服务”(BaaS)功能。Back4app 的 BaaS 选项提供各种功能,包括用户身份验证。
使用 Back4app 实施用户身份验证需要几个步骤。在本教程中,您将使用 React 构建一个简单的银行管理应用程序。
该应用程序将集成 Back4app 身份验证功能,允许您创建账户、登录账户、访问当前登录信息和注销。
创建 React 应用程序
要创建一个新的 React 应用程序,首先要使用 Vite 搭建一个新的 React 应用程序脚手架。Vite 是一款网络开发构建工具,可提供更快、更高效的开发体验。
在终端中运行以下命令,为新的 React 应用程序搭建脚手架:
npm init vite
运行上述命令后,屏幕上将显示一系列提示,要求您指定应用程序的名称、所选框架以及要使用的语言变量。
就像这样
在上图中,应用程序的名称是 react-authentication-app,选择的框架是 React,语言变量是 JavaScript。
接下来,将当前目录更改为应用程序目录,并运行以下命令安装必要的依赖项:
cd react-authentication-app && npm install
接下来,运行下面的命令在应用程序中安装 React Router:
npm install react-router-dom
接下来,在 IDE(集成开发环境)上打开 React 应用程序,然后用下面的代码块替换内容,修改main.jsx
文件。
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import './index.css'
import { BrowserRouter } from 'react-router-dom'
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>,
)
该代码块从react-router-dom
包中导入BrowserRouter
组件,并封装App
组件。
这样就可以在整个应用程序中启用路由。在应用程序
组件中,定义应用程序中的不同路由。
就像这样
import { Route, Routes } from "react-router-dom";
import Signup from "./pages/Signup";
import Login from "./pages/Login";
import Home from "./pages/Home";
function App() {
return (
<>
<Routes>
<Route path="/home" element={<Home />} />
<Route path="" element={<Signup />}/>
<Route path="/login" element={<Login />}/>
</Routes>
</>
)
}
export default App
上面的代码块定义了三个独立的路径,允许用户根据 URL 路径在注册、登录和主页之间导航。
现在,在应用程序的src
目录中创建一个组件文件夹。在该文件夹中,创建Authnavbar.jsx
文件。该组件将包含一个导航栏,显示在注册和登录页面上。
在Authnavbar
组件中编写以下代码:
import React from "react";
import { Link } from "react-router-dom";
function Authnavbar(props) {
return (
<nav>
<h3>Banka</h3>
{props.type === "signup" ? (
<div>
If you already have an account{""}
<Link to="/login" className="link">
Log in
</Link>
</div>
) : props.type === "login"? (
<div>
If you don't have an account{""}
<Link to="/" className="link">
Sign Up
</Link>
</div>
) : null}
</nav>
);
}
export default Authnavbar;
上面的代码块根据类型
道具的值创建了一个有条件呈现的导航栏,允许用户在应用程序中的注册页面和登录页面之间导航。
接下来,在应用程序的src
目录中生成一个页面
文件夹。在该文件夹中创建三个组件:Home.jsx
、Sign-up.jsx
和Login.jsx
。这些文件将作为主页、注册页面和登录页面。
注册
页面将包含一个表单,用户可在此输入用户名、电子邮件和密码等详细信息。
例如
import React from "react";
import Authnavbar from "../components/Authnavbar";
function Signup() {
const [formData, setFormData] = React.useState({
username: "",
email: "",
password: "",
});
const handleChange = (event) => {
setFormData((prevState) => ({
...prevState,
[event.target.name]: event.target.value,
}));
};
return (
<>
<Authnavbar type= "sign-up"/>
<form>
<input
type= "text"
name= "username"
placeholder= "Username..."
onChange={handleChange}
value={formData.username}
/>
<input
type= "email"
name= "email"
placeholder= "Email..."
onChange={handleChange}
value={formData.email}
/>
<input
type= "password"
name= "password"
placeholder= "Password..."
onChange={handleChange}
value={formData.password}
/>
<div>
<button>Sign Up</button>
</div>
</form>
</>
);
}
export default Sign-up;
该代码块表示一个注册页面。它包含一个带有输入字段的表单,其中包括用户的用户名、电子邮件和密码。
还有一个formData
状态,用于存储用户名、电子邮件和密码输入字段的值。每当用户输入输入框时,handleChange
函数就会更新formData
状态。
在登录
组件中,编写以下几行代码:
import React from "react";
import Authnavbar from "../components/Authnavbar";
function Login() {
const [formData, setFormData] = React.useState({
username: "",
password: "",
});
const handleChange = (event) => {
setFormData((prevState) => ({
...prevState,
[event.target.name]: event.target.value,
}));
};
return (
<>
<Authnavbar type= "login"/>
<form>
<input
type= "text"
name= "username"
placeholder= "Username..."
onChange={handleChange}
value={formData.username}
/>
<input
type= "password"
name= "password"
placeholder= "Password..."
onChange={handleChange}
value={formData.password}
/>
<div>
<button>Log In</button>
</div>
</form>
</>
);
}
export default Login;
登录页面与注册页面非常相似,只是登录表单中没有电子邮件输入字段,formData
对象状态也缺少电子邮件
属性。
现在,用以下代码行替换index.css
文件中的代码,为应用程序添加样式:
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
color: #333333;
background-color: #E8F7F5;
inline-size: 50%;
margin: auto;
font-family: "Montserrat", sans-serif;
}
input{
padding: 0.7rem 1rem;
border-radius: 10px;
border: none;
outline: none;
color: #333333;
background-color: #FFFFFF;
font-family: "Montserrat", sans-serif;
inline-size: 100%;
}
input::placeholder{
font-family: "Montserrat", sans-serif;
font-weight: 500;
}
button{
padding: 0.7rem 1rem;
background-color: #00C3A5;
color: #FFFFFF;
font-family: "Montserrat", sans-serif;
font-size: 14px;
border-radius: 7px;
border: none;
}
form{
margin-block-start: 25%;
display: flex;
flex-direction: column;
gap: 2rem;
align-items: center;
}
nav{
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 0;
}
.link{
text-decoration: none;
color: #00C3A5;
}
设计好应用程序后,运行下面的命令启动应用程序:
npm run dev
运行上述命令后,您将获得http://localhost:5173/ 链接。在网络浏览器上导航至该链接,即可查看您的应用程序。
使用您定义的样式后,注册页面应如下所示:
登录页面应如下图所示:
现在您已经创建了 React 应用程序,需要创建一个新的 Back4app 应用程序来处理身份验证。
创建新的 Back4App 应用程序
要使用 Back4app,您需要有一个账户。如果您没有账户,可以免费注册。
在本教程中,您将使用 Back4app AI 代理创建一个新的 Back4app 应用程序。Back4app AI 代理是一个 AI 助手,可帮助您使用提示在 Back4app 上执行任务。
登录您的 Back4app 账户,找到并点击仪表板导航栏上的 “AI Agent“按钮(见下图)。
要使用 Back4app AI Agent 生成应用程序,请输入以下提示:
create a new application named react-authentication
您应该会收到类似下图所示的回复:
如上图所示,Back4app AI 代理创建了一个名为 react-authentication 的应用程序。您可以在 “我的应用程序 “网页上找到该应用程序。
您也可以使用 Back4app 直观的用户界面(UI)创建新的 Back4app 应用程序。
在 Back4app 上的 react-authentication 应用程序中,创建一个钱包类。该钱包类将保存有关用户钱包的宝贵信息。
您可以根据下面的提示使用人工智能代理创建类:
Create a Wallet class and add the following fields: balance, owner(relation to the User class indicating which user owns the wallet), createdAt, and updatedAt in the react-authentication app
AI Agent 将启动创建钱包类的过程,并添加指定的内容,如下图所示。
将 React 应用程序连接到 Back4app
创建 Back4app 应用程序后,您需要使用 Parse SDK 将 Back4app 应用程序连接到 React 应用程序。
运行以下命令在应用程序中安装 Parse:
npm install parse
接下来,在应用程序
组件中导入Parse
对象,并使用 Back4app 应用程序密钥对其进行配置,从而在应用程序中对其进行初始化。
就像这样
import Parse from 'parse';
Parse.initialize('YOUR_APP_ID', 'YOUR_JAVASCRIPT_KEY');
Parse.serverURL = '<https://parseapi.back4app.com/>';
将"YOUR_APP_ID "
和"YOUR
_
JAVASCRIPT_KEY "
替换为 Back4App 提供的相应密钥。使用 Back4app AI 代理创建应用程序后,您可以在屏幕上找到您的应用程序密钥。
请注意,应始终在应用程序中妥善保管密钥,最好使用环境变量。
使用 Parse SDK 实施用户身份验证
初始化 Parse 后,您就可以在 React 应用程序中实现用户身份验证了。
Back4App 会自动为用户身份验证提供一个User
类。该类有用户名
、密码
、电子邮件
等默认字段。
在注册
组件中添加以下代码行,以便在 React 应用程序中实现用户注册。
import Parse from "parse"
import { useNavigate } from "react-router-dom";
const navigate = useNavigate();
const signUpUser = async () => {
try {
const newUser = new Parse.User();
newUser.set("username", formData.username);
newUser.set("email", formData.email);
newUser.set("password", formData.password);
const user = await newUser.signUp();
let Wallet = Parse.Object.extend("Wallet");
let wallet = new Wallet();
let userPointer = {
__type: "Pointer",
className: "_User",
objectId: user.id,
};
wallet.set("owner", userPointer);
wallet.set("balance", 100);
wallet.save();
console.log(`${user} have successfully signed up`);
navigate("/login");
} catch (error) {
console.log("you encountered an error signing up");
}
};
上面的代码块使用react-router-dom
中的useNavigate
钩子,以编程方式导航到不同的路由。useNavigate
钩子会返回一个分配给变量navigate
的 navigate 函数。
signUpUser
函数负责注册新用户。该函数使用Parse.User
方法创建了一个新的 Parse 用户对象newUser
,并将其用户名
、电子邮件
和密码
属性值设置为formData
对象状态的相应属性值。然后在newUser
对象上异步调用signUp
方法。
代码创建新用户后,使用Parse.Object.extend
方法定义了一个名为 “Wallet “的 Parse 类。
然后,创建一个userPointer
对象,该对象代表一个指向用户的指针,类名为_User
,以及新注册用户的对象 ID。代码使用set
方法将钱包的所有者设置为userPointer
对象,并将钱包的初始余额设置为 100。
注册成功后,函数会记录一条成功信息,并使用navigate
函数重定向到登录路径。如果在注册过程中出现错误,则会捕获错误并记录错误信息。
接下来,创建一个handleSubmit
函数,调用signUpUser
函数。使用onSubmit
事件处理程序将此函数绑定到注册表单。
这样,当用户提交注册表单时,就会自动触发 handleSubmit 函数。
handleSubmit
函数应该如下所示:
const handleSubmit = (event) => {
event.preventDefault();
signUpUser();
};
为实现用户登录,您将创建一个logInUser
函数,用于保存登录用户的逻辑。
将下面的代码块添加到登录
组件中:
import Parse from "parse"
import { useNavigate } from "react-router-dom";
const navigate = useNavigate();
const logInUser = async () => {
try {
const user = await Parse.User.logIn(formData.username, formData.password);
console.log("User logged in successfully:", user);
navigate("/home");
} catch (error) {
console.log("Error logging in user:", error);
}
};
const handleSubmit = (event) => {
event.preventDefault();
logInUser();
};
logInUser
函数异步调用Parse.User
类的logIn
方法,从formData
对象状态中传入用户名
和密码
属性值。
该函数检查用户输入的用户名和密码是否与 Back4App 用户类中存储的用户名和密码一致。如果匹配,用户将成功登录。
使用onSubmit
事件将handleSubmit
函数绑定到登录表单。handleSubmit
函数将调用logInUser
函数并尝试登录用户。
登录后,Parse SDK 会管理用户的会话。你可以使用Parse.User.current
方法访问当前用户。你将在主页(Home
)组件中使用该方法。
打开 “主页 "
组件并编写以下代码:
import React from "react";
import Parse from "parse";
import { useNavigate } from "react-router-dom";
function Home() {
const navigate = useNavigate();
const [balance, setBalance] = React.useState(0);
const user = Parse.User.current();
const fetchBalance = async () => {
const Wallet = await Parse.Object.extend("Wallet");
const query = new Parse.Query(Wallet);
query.equalTo("owner", user);
const wallet = await query.first();
setBalance(wallet.get("balance"));
};
fetchBalance();
return (
<>
<nav>
<h1 className="title">Banka</h1>
<button>Log out</button>
</nav>
<div className="home">
<p className="top">Welcome {user.get("username")}</p>
<div className="balance-card">
<p>Total Wallet Balance</p>
<h1>{balance}</h1>
<button>Top Up</button>
</div>
<div className="features">
<div className="card">
<p>Pay Bills</p>
</div>
<div className="card">
<p>Airtime/Data</p>
</div>
<div className="card">
<p>Transfers</p>
</div>
<div className="card">
<p>Withdraw</p>
</div>
</div>
</div>
</>
);
}
export default Home;
上面的代码块代表应用程序的主页。fetchBalance
函数用于获取当前用户的钱包余额。
它使用Parse.Query
方法查询 “钱包 “类,并使用query.equalTo
方法对查询设置约束,以检索所有者
属性等于当前用户的钱包。
query.first
方法执行查询,并返回符合查询约束条件的第一个结果。
通过setBalance
函数,代码将钱包余额设置为余额
状态。代码会显示用户姓名及其钱包余额。
在代码块的 JSX 部分,您可以在类为balance-card
的div
标签中找到“充值 “按钮。
点击该按钮后,钱包余额将增加 10。为此,您将创建一个topUp
函数,其中包含增加余额的逻辑。
就像这样
const topUp = async () => {
const Wallet = await Parse.Object.extend("Wallet");
const query = new Parse.Query(Wallet);
query.equalTo("owner", user);
const wallet = await query.first();
wallet.increment("balance", 10);
const newBalance = await wallet.save();
setBalance(newBalance.get("balance"));
};
这段代码从 Parse 后台获取用户的钱包,使用increment
方法将余额递增 10,将更新后的钱包保存回后台,并更新余额
状态。使用 click 事件处理程序将topUp
函数绑定到“充值 “按钮。
接下来,在主页
组件中添加一个logOutUser
函数,负责注销用户。该函数应如下所示
const logOutUser = async () => {
try {
const user = await Parse.User.logOut();
console.log("User logged out successfully:", user);
navigate("/");
} catch (error) {
console.error("Error logging out user:", error);
}
};
logOutUser
函数异步调用Parse.User
类的logOut
方法来注销当前用户。使用 click 事件将logOutUser
函数绑定到主页
组件中的“注销 “按钮。
要设置 “主页 "
组件的样式,请将下面定义的 CSS 类添加到index.css
文件中。
.home{
display: flex;
flex-direction: column;
gap: 3rem;
margin-block-start: 4rem;
}
.title{
text-align: center;
margin-block-start: 2rem;
}
.top{
font-size: 25px;
font-weight: 500;
}
.balance-card{
background-color: #FFFFFF;
inline-size: 40%;
padding: 1rem 2rem;
border-radius: 7px;
display: flex;
flex-direction: column;
gap: 2rem;
}
.features{
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 2rem;
}
.card{
background-color: #FFFFFF;
color: #00C3A5;
margin-block-end: 1rem;
padding: 1rem 2rem;
font-size: 25px;
border-radius: 10px;
}
.card:hover{
opacity: 0.6;
}
测试应用程序
完成 React 应用程序的构建并使用 Back4app 实现用户身份验证后,您就可以开始使用 Back4app 了。
下一步是测试应用程序。为此,请在网络浏览器上导航至链接http://localhost:5173/,注册页面就会显示在您的屏幕上。
填写报名表并提交。
注册后,您可以访问 Back4app 上的应用程序控制面板确认注册是否成功。如果注册成功,Back4app 将把用户详细信息添加到应用程序的用户类中。
就像这样
注册后,应用程序会将您重定向到登录页面,您可以使用在注册表单中使用的用户名和密码登录。
例如
登录后,屏幕上将显示主页,应该是这样的:
现在点击“充值 “按钮,将余额增加 10。
在 Back4app 上部署 React 应用程序
要在 Back4app 上部署 React 应用程序,您需要使用 Back4app 的容器即服务(CaaS)应用程序。
Back4app 的 CaaS允许您在 Back4App 提供的云环境中部署和管理 Docker 容器。
在部署 React 应用程序之前,首先需要对应用程序进行 dockerize。为此,请在应用程序的根目录下创建一个Dockerfile
,并添加以下代码行:
FROM node:16
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 5173
CMD ["npm", "run", "dev"]
该Dockerfile
设置了 Node.js 环境,创建了工作目录,安装了依赖项,复制了应用程序代码,公开了端口,并指定了运行应用程序的默认命令。
此外,还要创建一个.dockerignore
文件。在.dockerignore
文件中,添加在构建 Docker 镜像时从上下文中排除的文件和目录。
例如
#.dockerignore
node_modules
由于您使用 Vite 创建了 React 应用程序,因此必须更新 Vite 配置文件以支持 Docker。在vite.config.js
文件中,用下面的代码块替换现有代码:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// <https://vitejs.dev/config/>
export default defineConfig({
plugins: [react()],
server: {
host: true,
strictPort: true,
port: 5173,
},
})
该代码块设置服务器使用默认主机,通常是localhost
。它将开发服务器监听的端口号设置为 5173 端口,并确保在指定端口不可用时,Vite 将无法启动服务器。
现在,你可以在终端运行以下命令来构建应用程序的 docker 镜像:
docker build -t quote-generator .
在尝试在 Back4app 上部署应用程序之前,确保将应用程序推送到 GitHub 账户。推送应用程序完成后,将 GitHub 账户与 Back4app 整合。
您可以使用Back4app Github 应用程序实现这一功能。将 GitHub 与 Back4app 集成后,您就可以使用 Back4app AI 代理部署应用程序了。
要部署应用程序,请输入以下提示:
Deploy my repository <<repository-url>> on Back4app containers
在上述代码块中,将repository-url
替换为应用程序的 GitHub 仓库 URL。
如上图所示,在与人工智能代理通信时,请提供您要部署的应用程序的 GitHub 仓库链接。
Back4app 的人工智能代理启动应用程序部署后,请等待几分钟,然后确认部署的当前状态。
例如
部署成功后,Back4app AI 代理会将应用程序的部署状态更新为“已部署”,并为您提供一个链接,以便您在浏览器上访问应用程序。
您可以在这个GitHub 仓库中找到完成的应用程序,在这个 URL 中找到实时应用程序。
结论
本文介绍了如何使用后台服务为 React 应用程序添加身份验证。
使用 Back4App 将用户身份验证集成到您的 React 应用程序中是一个简单直接的过程,可显著增强应用程序的安全性和功能性。
利用 Back4App 的服务,您可以专注于构建具有良好用户体验的网络应用程序,而将后台管理和身份验证任务交给可靠的平台。