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