H

How to manage user authentication With React JS

2025-05-27

如何使用 React JS 管理用户身份验证

在开始之前,我希望你也看看这篇关于金融科技中收费 API 工作原理的文章。请点击此处

用户访问管理是 Web 应用程序开发的关键环节。在本指南中,您将学习并理解 React.js 中授权和身份验证的复杂工作原理。本文面向对 React 有一定了解的读者,为他们提供宝贵的见解。此外,经验丰富的前端工程师将在本指南中找到会话管理的详细工作流程。

首先,你需要通过运行以下命令来设置一个React 项目

npx create-react-app your-project-name
Enter fullscreen mode Exit fullscreen mode

另外,你可以运行

npm install react-router-dom
Enter fullscreen mode Exit fullscreen mode

这将帮助您安装React Router Dom以实现高效的路由系统。

构建登录组件

我们将从一个简单的登录组件开始,它接受两个输入:一个电子邮件字段和一个密码字段。当onChange事件发生时,这两个输入字段会触发相应的handleInput函数。该函数还会使用输入框上的 name 属性来设置输入状态。这是在 ReactJS 中管理输入字段的有效方法。如果按钮被按下,父组件会监听事件onSubmit并调用handleSubmitEvent相应的处理程序。

import { useState } from "react";

const Login = () => {
  const [input, setInput] = useState({
    username: "",
    password: "",
  });

  const handleSubmitEvent = (e) => {
    e.preventDefault();
    if (input.username !== "" && input.password !== "") {
      //dispatch action from hooks
    }
    alert("please provide a valid input");
  };

  const handleInput = (e) => {
    const { name, value } = e.target;
    setInput((prev) => ({
      ...prev,
      [name]: value,
    }));
  };

  return (
    <form onSubmit={handleSubmitEvent}>
      <div className="form_control">
        <label htmlFor="user-email">Email:</label>
        <input
          type="email"
          id="user-email"
          name="email"
          placeholder="example@yahoo.com"
          aria-describedby="user-email"
          aria-invalid="false"
          onChange={handleInput}
        />
        <div id="user-email" className="sr-only">
          Please enter a valid username. It must contain at least 6 characters.
        </div>
      </div>
      <div className="form_control">
        <label htmlFor="password">Password:</label>
        <input
          type="password"
          id="password"
          name="password"
          aria-describedby="user-password"
          aria-invalid="false"
          onChange={handleInput}
        />
        <div id="user-password" className="sr-only">
          your password should be more than 6 character
        </div>
      </div>
      <button className="btn-submit">Submit</button>
    </form>
  );
};

export default Login;
Enter fullscreen mode Exit fullscreen mode

特雷西洛金
此图显示了我们的登录组件的输出,其中包含两个输入字段和一个按钮。

创建 AuthContext 和 AuthProvider

上下文API通常用于管理整个应用程序所需的状态。例如,我们需要仪表板组件中作为登录响应的一部分返回的用户数据或令牌。此外,应用程序的某些部分也需要用户数据,因此使用上下文 API 不仅仅是解决问题。

接下来,在一个AuthProvider.js文件中,创建一个 AuthContext用于管理用户状态的文件和一个 AuthProvider 用于使用上下文内容的文件。

import { useContext, createContext } from "react";
const AuthContext = createContext();

const AuthProvider = ({ children }) => {
  return <AuthContext.Provider>{children}</AuthContext.Provider>;
};

export default AuthProvider;

export const useAuth = () => {
  return useContext(AuthContext);
};
Enter fullscreen mode Exit fullscreen mode

上面设置的代码用于使用 Context API 在 React 中创建身份验证上下文。它创建了一个AuthContext用于createContext()管理身份验证状态的实例。

AuthProvider组件旨在包装应用程序并使用向其子组件提供身份验证上下文AuthContext.Provider

useAuth 自定义钩子用于useContext组件内部访问身份验证上下文,允许组件使用存储在上下文中的身份验证状态和相关函数。随着本文的进展,我们将添加控制登录和注销过程的身份验证逻辑,并通过 AuthContext.Provider 传递它们。之后,您将可以访问它们,并在调用 useAuth 函数时使用它们。

接下来,导入并包装AuthProvider应用程序内容App.js

import AuthProvider from "./hooks/AuthProvider";

function App() {
  return (
    <div className="App">
      <AuthProvider>{/* App content */}</AuthProvider>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

现在AuthProvider已经包裹了 App 组件,当我们向 App 组件添加所需的所有路由时,我们可以访问应用程序内任何页面或组件中的所有上下文值。

创建身份验证逻辑

接下来,AuthProvider 组件将更新登录和注销功能。该功能将通过 向下传递AuthContext.Provider,并可在全局范围内访问。

import { useContext, createContext, useState } from "react";
import { useNavigate } from "react-router-dom";

const AuthContext = createContext();

const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null);
  const [token, setToken] = useState(localStorage.getItem("site") || "");
  const navigate = useNavigate();
  const loginAction = async (data) => {
    try {
      const response = await fetch("your-api-endpoint/auth/login", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(data),
      });
      const res = await response.json();
      if (res.data) {
        setUser(res.data.user);
        setToken(res.token);
        localStorage.setItem("site", res.token);
        navigate("/dashboard");
        return;
      }
      throw new Error(res.message);
    } catch (err) {
      console.error(err);
    }
  };

  const logOut = () => {
    setUser(null);
    setToken("");
    localStorage.removeItem("site");
    navigate("/login");
  };

  return (
    <AuthContext.Provider value={{ token, user, loginAction, logOut }}>
      {children}
    </AuthContext.Provider>
  );

};

export default AuthProvider;

export const useAuth = () => {
  return useContext(AuthContext);
};
Enter fullscreen mode Exit fullscreen mode

在此代码中,AuthProvider组件管理用户身份验证状态,使用useState 钩子提供登录、注销和令牌存储等功能。

该函数通过向身份验证端点发送POST 请求、在成功响应后更新用户和令牌状态以及将令牌存储在本地存储loginAction中来处理用户登录

logOut函数清除用户和令牌数据,将令牌从本地存储中删除。这AuthContext.Provider使得其子组件可以通过useAuth钩子访问身份验证状态和相关函数,从而使组件能够在应用程序内使用身份验证数据和操作。

使用授权保护路线

接下来,我们将设置一个路由守卫,用于保护应用程序中所有私有的路由。为此,我们useAuth需要一个用于访问 context 数据的钩子。以下是实现该钩子的代码。

import React from "react";
import { Navigate, Outlet } from "react-router-dom";
import { useAuth } from "../hooks/AuthProvider";

const PrivateRoute = () => {
  const user = useAuth();
  if (!user.token) return <Navigate to="/login" />;
  return <Outlet />;
};

export default PrivateRoute;
Enter fullscreen mode Exit fullscreen mode

这段代码定义了一个PrivateRoute用于处理身份验证的组件。它利用useAuth中的钩子AuthProvider来访问用户身份验证数据。如果用户没有令牌,即表示他们尚未登录,代码会触发重定向到/login使用该组件的路由。否则,它会渲染嵌套在通过 访问的组件<Navigate>中的子组件,允许经过身份验证的用户访问受保护的路由,同时将未经身份验证的用户重定向到登录页面。PrivateRoute<Outlet />

添加路由

接下来,我们将App.js通过添加路由来更新组件。它作为根组件,封装了整个应用程序。在组件内部App.js,它使用 Router 组件来设置路由机制。

import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import Login from "./components/Login";
import Dashboard from "./components/Dashboard";
import AuthProvider from "./hooks/AuthProvider";
import PrivateRoute from "./router/route";

function App() {
  return (
    <div className="App">
      <Router>
        <AuthProvider>
          <Routes>
            <Route path="/login" element={<Login />} />
            <Route element={<PrivateRoute />}>
              <Route path="/dashboard" element={<Dashboard />} />
            </Route>
            {/* Other routes */}
          </Routes>
        </AuthProvider>
      </Router>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Routes组件建立路由配置:'/login' 路径映射到 Login 组件,并在 URL 匹配时渲染该组件。该<PrivateRoute />组件充当路由的守卫/dashboard。当用户导航到 时/dashboard,会PrivateRoute使用 进行身份验证AuthProvider。如果用户已通过身份验证(拥有令牌),则会渲染 Dashboard 组件;否则,它会重定向到/login路由,以确保对仪表板的访问受到保护。

API 集成

如果您已经读到这里,那就太棒了!本文即将结束。不过,还有一些步骤需要介绍。我们已经成功创建了一个登录组件,建立了一个 AuthContext 来管理用户会话,并设置了一个路由守卫。现在,下一步是利用useAuth钩子访问函数来触发登录操作。这种方法使handleSubmitEvent登录组件中的函数能够触发 API 请求。响应成功后,令牌和用户数据将被保存并通过 AuthContext 传递下去。

这是登录组件的更新代码。

import { useState } from "react";
import { useAuth } from "../hooks/AuthProvider";

const Login = () => {
  const [input, setInput] = useState({
    username: "",
    password: "",
  });

  const auth = useAuth();
  const handleSubmitEvent = (e) => {
    e.preventDefault();
    if (input.username !== "" && input.password !== "") {
      auth.loginAction(input);
      return;
    }
    alert("pleae provide a valid input");
  };

  return (
    <form onSubmit={handleSubmitEvent}>
      {/* Form inputs are provided in the above examples */}
    </form>
  );
};

export default Login;
Enter fullscreen mode Exit fullscreen mode

上面的例子展示了如何loginAction使用useAuth钩子来调度。

添加注销按钮

接下来,我们需要添加一个按钮来调度logOut结束用户会话的操作,通过清除上下文中的用户状态并明确 localStorage 令牌。现在创建一个仪表板组件并添加以下代码。

import React, { useEffect } from "react";
import { useAuth } from "../hooks/AuthProvider";

const Dashboard = () => {
  const auth = useAuth();
  return (
    <div className="container">
      <div>
        <h1>Welcome! {auth.user?.username}</h1>
        <button onClick={() => auth.logOut()} className="btn-submit">
          logout
        </button>
      </div>
    </div>
  );
};

export default Dashboard;
Enter fullscreen mode Exit fullscreen mode

在上面的代码中,Dashboard 组件利用useAuth中的钩子来AuthProvider访问身份验证信息。该组件显示一条欢迎消息,其中包含已登录用户的用户名和一个注销按钮,该按钮触发logOut注销用户的功能。 上图显示了两个输入字段和一个按钮。用户输入电子邮件地址和密码。 此图展示了用户输入详细信息后,输入数据作为对象传递到后端的过程。 此图描述了后端 API 的响应数据,其中包括用户数据、用户任务以及用于管理用户会话的令牌。 成功登录后,用户将被重定向到仪表板,其中显示用户名和注销按钮。
特雷西洛金

要求

c-2

仪表板测试

提供的图像展示了我们实现的登录流程。当用户输入正确的信息时,它会将其作为有效负载发送到服务器,服务器会检查用户是否退出。如果退出,我们会收到一个包含所有用户信息(例如姓名和电子邮件地址)的用户对象的响应,然后用户将被重定向到仪表板页面。此外,我们还会收到一个令牌,该令牌保存在浏览器的本地存储中。这使我们能够更有效地管理用户会话。当用户点击注销操作时,将执行最后一个操作。它会清除用户的本地存储并将其重定向到登录页面。

结论

了解如何在身份验证工作流中使用 Context API 和 React Router 对于管理 React 应用程序中的用户会话至关重要。从创建身份验证上下文到创建受保护的路由,再到启用登录和注销等用户操作,本指南内容全面,可帮助开发人员在 React 项目中无缝安全地处理用户身份验证。

文章来源:https://dev.to/miracool/how-to-manage-user-authentication-with-react-js-3ic5
PREV
别让庞大的代码库吓到你!解读他人代码的技巧和工具
NEXT
Git 解释:基础知识