React

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > React > React Router JWT校验

探讨JWT身份校验与React-router无缝集成

作者:superZidan

这篇文章主要为大家介绍了JWT身份校验与React-router无缝集成的探讨解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

引言

这篇文章想跟大家聊聊 在React Router 中使用 JWT 

在这篇文章中,我们将探讨 JWT 身份校验与 React 和 React-router 的无缝集成。 我们还将学习如何处理公共路由、受校验保护路由,以及如何利用 axios 库通过身份验证令牌(token)发出 API 请求。

创建一个 React 项目

使用下方的指令会为我们创建一个项目

$ npm create vite@latest react-jwt-cn

然后我们选择 react 和 javascript 作为我们的框架和语言。在项目开始之前,我们要确保所有的依赖都已经被安装,所以我们要先执行

$ npm install

安装完毕后,在项目的根目录下,我们可以运行下面的指令来启动我们的项目

$ npm run dev

我们通过这些步骤来让我们的 React 项目顺利启动和运行

安装 React-Router 和 Axios

在我们继续之前,要确保我们已经为我们的项目安装了必要的依赖项。 我们将从安装 react-router v6 开始,它将处理我们的 React 应用程序中的路由。 此外,我们将安装 Axios,这是一个用于发送 API 请求的库。 通过执行这些步骤,我们将配备实现无缝路由和执行高效 API 通信所需的工具。 让我们从安装这些依赖项开始。

$ npm install react-router-dom axios

在 React 中创建 AuthProvider 和 AuthContext

接下来我们要实现的就是 JWT 身份验证的功能。在这个小节中我们将创建一个 AuthProvider 组件和一个关联的 AuthContext 。这将协助我们在整个应用中存储和共享 JWT 身份验证相关的数据和函数

在 src > provider 下创建 authProvider.js 。然后我们来探 AuthProvider 和 AuthContext 的实现

import axios from "axios";
import {
  createContext,
  useContext,
  useEffect,
  useMemo,
  useState,
} from "react";
const AuthContext = createContext();
const AuthProvider = ({ children }) => {
  // 组件内容写在这里
};
const [token, setToken_] = useState(localStorage.getItem("token"));
const setToken = (newToken) => {
  setToken_(newToken);
};
useEffect(() => {
  if (token) {
    axios.defaults.headers.common["Authorization"] = "Bearer " + token;
    localStorage.setItem('token',token);
  } else {
    delete axios.defaults.headers.common["Authorization"];
    localStorage.removeItem('token')
  }
}, [token]);
const contextValue = useMemo(
  () => ({
    token,
    setToken,
  }),
  [token]
);
return (
  <AuthContext.Provider value={contextValue}>
    {children}
  </AuthContext.Provider>
);
export const useAuth = () => {
  return useContext(AuthContext);
};
export default AuthProvider;

完整代码

import axios from "axios";
import {
  createContext,
  useContext,
  useEffect,
  useMemo,
  useState,
} from "react";
const AuthContext = createContext();
const AuthProvider = ({ children }) => {
    const [token, setToken_] = useState(localStorage.getItem("token"));
    const setToken = (newToken) => {
        setToken_(newToken);
    };
    useEffect(() => {
        if (token) {
          axios.defaults.headers.common["Authorization"] = "Bearer " + token;
          localStorage.setItem('token',token);
        } else {
          delete axios.defaults.headers.common["Authorization"];
          localStorage.removeItem('token')
        }
    }, [token]);
    const contextValue = useMemo(
        () => ({
          token,
          setToken,
        }),
        [token]
    );
    return (
        <AuthContext.Provider value={contextValue}>
          {children}
        </AuthContext.Provider>
    );
};
export const useAuth = () => {
    return useContext(AuthContext);
};
export default AuthProvider;

小结,此代码使用 React 的 context API 设置身份验证上下文。 它通过 context 向子组件提供身份验证令牌和 setToken 函数。 它还确保在身份验证令牌更新时可以及时更新 axios 中的默认授权请求头。

为 JWT 身份验证创建路由

为了能够更高效的组织路由,我们将创建一个 src > routes 目录。在这个目录里,我们将创建一个 index.jsx 文件,这个文件用来作为定义整个应用路由的入口。通过在单独的文件夹中构建我们的路由,我们可以保持清晰且易于管理的路由结构。让我们继续创建路由并探索如何将 JWT 身份验证集成到我们的 React 应用程序中。

为身份验证路由创建受保护路由组件

为了保护我们身份验证的路由并防止未经授权的访问,我们将创建一个名为 ProtectedRoute 的组件。这个组件将包裹我们的身份验证路由,以确保只有被授权的用户才能够访问。通过现实这个组件,我们可以轻松完成身份验证需求并提供良好的用户体验。我们将在 src > routes 下创建 ProtectedRoute.jsx 文件

import { Navigate, Outlet } from "react-router-dom";
import { useAuth } from "../provider/authProvider";
export const ProtectedRoute = () => {
    const { token } = useAuth();
    // 判断用户是否有权限
    if (!token) {
      // 如果没有授权,则跳转到登录页面
      return <Navigate to="/login" />;
    }
    // 如果已经授权,则直接渲染子组件
    return <Outlet />;
 };

小结,ProtectedRoute 组件充当了身份验证的路由的守卫。 如果用户未通过身份验证,他们将被重定向到登录页面。 如果用户通过身份验证,则 ProtectedRoute 组件中定义的子路由将使用 Outlet 组件呈现。

上述代码使我们能够根据用户的身份验证状态轻松保护特定路由并控制访问,从而在我们的 React 应用程序中提供安全的导航体验。

深入探索路由

现在我们已经有了 ProtectedRoute 组件和身份验证上下文,我们可以继续定义我们的路由。通过区分公共路由、受校验保护路由和非认证用户路由,我们可以有效地处理基于 JWT 认证的导航和访问控制。接下来我们将深入到 src > routes > index.jsx 文件并探索如何将 JWT 身份校验集成到我们的路由结构中

import { RouterProvider, createBrowserRouter } from "react-router-dom";
import { useAuth } from "../provider/authProvider";
import { ProtectedRoute } from "./ProtectedRoute";
const Routes = () => {
  const { token } = useAuth();
  // 路由配置写在这里
};
const { token } = useAuth();
const routesForPublic = [
  {
    path: "/service",
    element: <div>Service Page</div>,
  },
  {
    path: "/about-us",
    element: <div>About Us</div>,
  },
];
const routesForAuthenticatedOnly = [
  {
    path: "/",
    element: <ProtectedRoute />,
    children: [
      {
        path: "/",
        element: <div>User Home Page</div>,
      },
      {
        path: "/profile",
        element: <div>User Profile</div>,
      },
      {
        path: "/logout",
        element: <div>Logout</div>,
      },
    ],
  },
];
const routesForNotAuthenticatedOnly = [
  {
    path: "/",
    element: <div>Home Page</div>,
  },
  {
    path: "/login",
    element: <div>Login</div>,
  },
];
const router = createBrowserRouter([
  ...routesForPublic,
  ...(!token ? routesForNotAuthenticatedOnly : []),
  ...routesForAuthenticatedOnly,
]);
return <RouterProvider router={router} />;

完整代码

import { RouterProvider, createBrowserRouter } from "react-router-dom";
import { useAuth } from "../provider/authProvider";
import { ProtectedRoute } from "./ProtectedRoute";
const Routes = () => {
  const { token } = useAuth();
  // 公共路由配置
  const routesForPublic = [
    {
      path: "/service",
      element: <div>Service Page</div>,
    },
    {
      path: "/about-us",
      element: <div>About Us</div>,
    },
  ];
  // 授权的用户才可以访问的路由配置
  const routesForAuthenticatedOnly = [
    {
      path: "/",
      element: <ProtectedRoute />, // Wrap the component in ProtectedRoute
      children: [
        {
          path: "/",
          element: <div>User Home Page</div>,
        },
        {
          path: "/profile",
          element: <div>User Profile</div>,
        },
        {
          path: "/logout",
          element: <div>Logout</div>,
        },
      ],
    },
  ];
  // 没有授权的用户才可以访问的路由配置
  const routesForNotAuthenticatedOnly = [
    {
      path: "/",
      element: <div>Home Page</div>,
    },
    {
      path: "/login",
      element: <div>Login</div>,
    },
  ];
  // 合并路由配置
  const router = createBrowserRouter([
    ...routesForPublic,
    ...(!token ? routesForNotAuthenticatedOnly : []),
    ...routesForAuthenticatedOnly,
  ]);
  return <RouterProvider router={router} />;
};
export default Routes;

最后整合

现在我们已经准备好了 AuthContextAuthProvider  和  Routes 。让我们把它们整合到 App.jsx

import AuthProvider from "./provider/authProvider";
import Routes from "./routes";
return (
  <AuthProvider>
    <Routes />
  </AuthProvider>
);

完整代码

import AuthProvider from "./provider/authProvider";
import Routes from "./routes";
function App() {
  return (
    <AuthProvider>
      <Routes />
    </AuthProvider>
  );
}
export default App;

实现登录与登出

在 src > pages > Login.jsx 创建 登录页面

const Login = () => {
  const { setToken } = useAuth();
  const navigate = useNavigate();
  const handleLogin = () => {
    setToken("this is a test token");
    navigate("/", { replace: true });
  };
  setTimeout(() => {
    handleLogin();
  }, 3 * 1000);
  return <>Login Page</>;
};
export default Login;

现在,我们在 src > pages > Logout.jsx 创建一个 登出页面

import { useNavigate } from "react-router-dom";
import { useAuth } from "../provider/authProvider";
const Logout = () => {
  const { setToken } = useAuth();
  const navigate = useNavigate();
  const handleLogout = () => {
    setToken();
    navigate("/", { replace: true });
  };
  setTimeout(() => {
    handleLogout();
  }, 3 * 1000);
  return <>Logout Page</>;
};
export default Logout;

现在,我们将用更新后的版本替换路由组件中的登录和登出组件

const routesForNotAuthenticatedOnly = [
  {
    path: "/",
    element: <div>Home Page</div>,
  },
  {
    path: "/login",
    element: <Login />,
  },
];

在 routesForNotAuthenticatedOnly 数组中,“/login” 的 element 属性设置为 <Login />,表示当用户访问 “/login” 路径时,会渲染 Login 组件

const routesForAuthenticatedOnly = [
  {
    path: "/",
    element: <ProtectedRoute />,
    children: [
      {
        path: "/",
        element: <div>User Home Page</div>,
      },
      {
        path: "/profile",
        element: <div>User Profile</div>,
      },
      {
        path: "/logout",
        element: <Logout />,
      },
    ],
  },
];

在 routesForAuthenticatedOnly 数组中,“/logout” 的 element 属性设置为 <Logout />,表示当用户访问 “/logout” 路径时,会渲染 Logout 组件

测试流程

此流程演示了登录和登出过程,其中用户在经过身份验证和未经过身份验证的状态之间转换,并相应地显示相应的路由。

以上就是本篇文章的全部内容,感谢大家对本文的支持~欢迎点赞收藏,在评论区留下你的高见 🌹🌹🌹

其他

以上就是探讨JWT身份校验与React-router无缝集成的详细内容,更多关于React Router JWT校验的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文