React 路由身份验证

Rana Hasnain Khan 2022年5月18日
React 路由身份验证

我们将在 React 应用程序中介绍受保护的路由和使用 react-router 的身份验证。

React 中的 React 路由身份验证

在 React 中构建商业 Web 应用程序或网站时,我们经常需要对未登录或不具有访问这些路由所需的特定用户角色的用户隐藏应用程序中的某些路由。

React 路由为我们提供了受保护的路由;他们让我们根据用户角色或是否登录来选择用户可以访问的路由。

例如,我们有一个所有用户都可以访问的 homeaboutcontactlogin 页面。但受保护的路由,如仪表板配置文件设置只能由登录用户访问。

React 路由没有为此提供任何功能,但添加此功能非常简单直接。首先,我们需要添加功能来验证用户以开始处理受保护的路由。

我们将使用假的 AuthUser Hook 来检查身份验证状态。

让我们使用以下命令创建一个新应用程序。

# react
npx create-react-app my-app

在 React 中创建我们的新应用程序后,我们将使用此命令转到我们的应用程序目录。

# react
cd my-app

现在,让我们运行我们的应用程序来检查所有依赖项是否安装正确。

# react
npm start

我们将在 src 文件夹中创建一个新文件 AuthUser.js。一旦我们创建了一个新文件,现在我们将创建一个上下文并将其分配给一个常量 authUserContext

# react
const authUserContext = React.createContext();

一旦我们创建了一个上下文,现在我们将创建一个函数 AuthUser,它将两个变量的状态设置为 authenticatesetAuthenticate 为 false,我们将使用它来检查用户是否经过身份验证。

我们将创建 2 个方法来返回 login()logout()login() 会将 setAuthenticate 的值设置为 true,而 logout() 会将其设置回 false。

现在,我们将导出函数 AuthenticationProvider,它将 AuthUser() 保存在一个常量 auth 中。所以我们在 AuthUser.js 中的代码将如下所示。

import * as React from "react";

const authUserContext = React.createContext();

function AuthUser() {
  const [authenticate, setAuthenticate] = React.useState(false);

  return {
    authenticate,
    login() {
      return new Promise((res) => {
        setAuthenticate(true);
        res();
      });
    },
    logout() {
      return new Promise((res) => {
        setAuthenticate(false);
        res();
      });
    }
  };
}

export function AuthenticationProvider({ children }) {
  const auth = AuthUser();

  return (
    <authUserContext.Provider value={auth}>{children}</authUserContext.Provider>
  );
}

export default function AuthenticateConsumer() {
  return React.useContext(authUserContext);
}

每当我们想使用 authenticatelogin()logout() 时,我们都可以使用 AuthUser Hook。我们将开始构建导航,它将包含 5 个组件 HomeAboutProfileLoginDashboard

HomeAboutLogin 将是公开访问的,而 DashboardProfile 只有在用户通过身份验证后才能访问。

首先,我们将从 react-router-dom 导入 LinkRoutesRouteUseNavigateuserLocation。我们还将从我们创建的新文件中导入 AuthUser

# react
import * as React from "react";
import {
  Link,
  Routes,
  Route,
  useNavigate,
  Navigate,
  useLocation
} from "react-router-dom";
import AuthUser from "./AuthUser";

现在,我们将为访问某个导航链接时显示的导航定义常量。

如果是可公开访问的链接,则会显示公共路由,如果是私有链接,则只有在用户通过身份验证后才会显示私有路由。否则,它将被重定向到登录页面。

# react
const Home = () => <h1>Home (Public Route)</h1>;
const About = () => <h1>About (Public Route)</h1>;

const Dashboard = () => <h1>Dashboard (Private)</h1>;
const Profile = () => <h1>Profile (Private)</h1>;

现在我们将为 Login 方法创建一个常量,我们将在其中登录用户,并在验证后将其重定向到 dashboard

如果用户未登录,它将返回一个登录页面内容,每当未经身份验证的用户尝试访问私有页面时,都会显示该登录页面内容。

const Login = () => {
  const navigate = useNavigate();
  const { login } = AuthUser();
  const { state } = useLocation();

  const handleLogin = () => {
    login().then(() => {
      navigate(state?.path || "/dashboard");
    });
  };

  return (
    <div>
      <h1>Login</h1>
      <button onClick={handleLogin}>Log in</button>
    </div>
  );
};

现在我们将创建一个导航函数,其中我们将返回一个导航栏,其中包含所有路由,包括公共和私有路由,如果用户未通过身份验证,则带有登录按钮,如果用户通过身份验证,则会显示注销按钮。

我们还将创建 2 个方法,handleLogouthandleLogin

function Nav() {
  const { authenticate, logout, login } = AuthUser();
  const navigate = useNavigate();

  const handleLogout = () => {
    logout();
    navigate("/");
  };
  const handleLogin = () => {
    login();
    navigate("/dashboard");
  };

  return (
    <nav>
      <ul>
        <li>
          <Link to="/">Home</Link>
        </li>
        <li>
          <Link to="/about">About</Link>
        </li>
        <li>
          <Link to="/dashboard">Dashboard</Link>
        </li>
        <li>
          <Link to="/profile">Profile</Link>
        </li>
        <li>{!authenticate && <button onClick={handleLogin}>Login</button>}</li>
      </ul>
      {authenticate && <button onClick={handleLogout}>Logout</button>}
    </nav>
  );
}

我们将创建一个函数 RequireAuthentication,每当用户尝试访问私有路由时,该函数将对用户进行身份验证。

function RequireAuthentication({ children }) {
  const { authenticate } = AuthUser();
  const location = useLocation();

  return authenticate === true ? (
    children
  ) : (
    <Navigate to="/login" replace state={{ path: location.pathname }} />
  );
}

在我们的 App() 函数中,我们将定义我们的路由。

export default function App() {
  return (
    <div>
      <Nav />

      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route
          path="/dashboard"
          element={
            <RequireAuthentication>
              <Dashboard />
            </RequireAuthentication>
          }
        />
        <Route
          path="/profile"
          element={
            <RequireAuthentication>
              <Profile />
            </RequireAuthentication>
          }
        />
        <Route path="/login" element={<Login />} />
      </Routes>
    </div>
  );
}

让我们测试我们的应用程序并检查它是如何工作的。请参阅此处的演示。

输出:

React 路由认证示例

正如你在上面的示例中看到的那样,设置经过身份验证的路由非常容易,但是我们使用的这个 AuthUser Hook 只是一个前端检查。

但是,如果我们正在开发一个合适的 Web 应用程序,我们需要在后端对用户进行身份验证以保护我们的系统。

Rana Hasnain Khan avatar Rana Hasnain Khan avatar

Rana is a computer science graduate passionate about helping people to build and diagnose scalable web application problems and problems developers face across the full-stack.

LinkedIn

相关文章 - React Router