实现路由守卫(JWT)—React篇

在 React 中,没有像 Vue 或 Angular 那样的内置路由守卫功能。但是,我们可以使用 React Router 或其他第三方库,结合一些自定义逻辑来实现类似的功能,接下来就让我们试试看吧。

JWT逻辑思维导图

结合导图,能更可观的了解整个流程,下面我们就直接上实操。

示例

以下是基于 React Router 实现路由守卫的基本示例:

假设:使用react-redux统一管理用户的状态

  1. 安装 React Router
csharp 复制代码
npm install react-router-dom react-redux
# 或者  
yarn add react-router-dom react-redux
  1. 定义一个外部处理高阶Layout:

创建一个自定义的 Layout 组件,该组件在渲染之前会检查某些条件(例如用户是否已登录)。如果条件不满足,则重定向到另一个页面(例如登录页)。

获取状态管理中的用户状态,判断是否存在Token,存在则拉取用户信息,并更新用户信息状态

typescript 复制代码
import { useSelector, useDispatch } from "react-redux";
export const Layout = (
  props: any
) => {
  const dispatch = useDispatch()
  const user = useSelector<any, { userInfo: UserInfo, token: string }>((state) => state.UserReduce)
   useEffect(() => {
    if (user.token) {

      getUserInfo<{ roles: string[], avatar: string, name: string }>()
        .then(res => {
          dispatch(setUserInfo(res.data))
        })
    }

  }, [user.token])

}

路由守卫逻辑:

  • 使用 useMemo Hook 来记忆(或缓存)根据路由和 token 决定的组件渲染结果。

  • component 变量存储了最终要渲染的组件或 null(表示需要重定向或不做任何操作)。

  • 路由守卫逻辑:

    • 如果 token 存在且当前路由是登录页('/login'),则使用 history.go(-1) 返回上一页。
    • 如果 token 不存在且当前路由不是登录页,则使用 window.location.replace 重定向到登录页,并带上当前路由作为查询参数。
    • 如果以上两种情况都不满足,则渲染 props.children(即传递给 Layout 组件的子组件)。
typescript 复制代码
export const Layout = (
  props: any
) => {
  const location = useLocation() 
  const dispatch = useDispatch() 
  const history = createBrowserHistory()
  const user = useSelector<any, { userInfo: UserInfo, token: string }>((state) => state.UserReduce) // redux数据
  
  useEffect(() => {
    if (user.token) {

      getUserInfo<{ roles: string[], avatar: string, name: string }>()
        .then(res => {
          dispatch(setUserInfo(res.data))
          
          if (res.code === 401) { // 清除token,并返回登录页
          
          }
        })
    }

  }, [user.token])

  const component = useMemo(() => { // 监听路由变化------------ 路由守卫
    
    const { pathname, search } = location
    const token = user.token

    if(token && pathname === '/login') {
      history.go(-1)
      return null
    }

    if(!token && pathname !== '/login') {
      window
        .location
        .replace(`/login?redirect=${pathname}${search ? search : ''}`)

      return null
    }

    return props.children
    
  }, [location.pathname])

  
  return component
}
  1. 定义一个路由管理组件RouteLink

定义 onEnter 函数

  • onEnter 是一个使用 useCallback Hook 定义的函数,它接收一个 Component 作为参数。
  • 这个函数返回一个新的 JSX 元素,该元素是一个 Layout 组件,Layout 组件内部包裹了传入的 Component
  • useCallback 的依赖项数组为空,因为onEnter不依赖于任何外部变量。
javascript 复制代码
/ 假设 ASSETS_MENUS 在组件外部已经定义好,并且是一个数组,每个元素都有 path 和 element 属性  
// const ASSETS_MENUS = [  
//   { path: '/', element: <HomePage /> },  
//   { path: '/about', element: <AboutPage /> },
 // { path: '/login', element: <Login /> }
//   // ... 其他路由配置  
// ];  

const RouterLink = () => {   
  const onEnter = React.useCallback((Component) => {  
    return <Layout><Component /></Layout>;  
  }, []); // 依赖项数组为空,因为onEnter不依赖于任何外部变量  
  
  return (  
    <div>  
      <BrowserRouter>  
        <Routes>  
          {ASSETS_MENUS.map((comp) => (  
            <Route  
              key={comp.path}  
              path={comp.path}  
              element={onEnter(comp.element)}  
            />  
          ))}  
        </Routes>  
      </BrowserRouter>  
    </div>  
  );  
};  
  1. APP入口中使用

直接使用就行了。

javascript 复制代码
const App = () => {  
  return (  
    <div>
        // 其他
        <RouterLink />
    </div>
  );  
};  

路由守卫只是前端的安全措施之一。仍然需要在后端实施适当的安全措施,以确保即使前端逻辑被绕过,敏感数据也不会被未经授权的用户访问。

相关推荐
apcipot_rain4 小时前
【应用密码学】实验五 公钥密码2——ECC
前端·数据库·python
油丶酸萝卜别吃4 小时前
OpenLayers 精确经过三个点的曲线绘制
javascript
ShallowLin4 小时前
vue3学习——组合式 API:生命周期钩子
前端·javascript·vue.js
Nejosi_念旧4 小时前
Vue API 、element-plus自动导入插件
前端·javascript·vue.js
互联网搬砖老肖4 小时前
Web 架构之攻击应急方案
前端·架构
pixle05 小时前
Vue3 Echarts 3D饼图(3D环形图)实现讲解附带源码
前端·3d·echarts
麻芝汤圆5 小时前
MapReduce 入门实战:WordCount 程序
大数据·前端·javascript·ajax·spark·mapreduce
juruiyuan1117 小时前
FFmpeg3.4 libavcodec协议框架增加新的decode协议
前端
Peter 谭7 小时前
React Hooks 实现原理深度解析:从基础到源码级理解
前端·javascript·react.js·前端框架·ecmascript
周胡杰8 小时前
鸿蒙接入flutter环境变量配置windows-命令行或者手动配置-到项目的创建-运行demo项目
javascript·windows·flutter·华为·harmonyos·鸿蒙·鸿蒙系统