【React】路由鉴权

需求

  1. 未登录状态下,某些页面不可访问,白名单中的页面可以。
  2. 未登录状态下,拦截通过修改url直接访问页面。
  3. 判断是否有权访问某些页面。
  4. 路由规则中每个页面都需要调用某个接口。

前提

使用的react-router-dom6 ,这里只是举例,具体细节根据项目调整。

路由表生成路由规则

import { Navigate, Outlet, RouteObject, useRoutes } from "react-router-dom"import MyLayout from "@/layout/index"
// 无需Layout的组件
import Login from "@/views/Login/Login"
import NotFound from "@/views/NotFound/NotFound"
// 组件
import Dashboard from "@/views/Dashborad/Dashboard"
import Project from "@/views/Project/Project"
import Test1 from "@/views/Setting/Test1"
import Test2 from "@/views/Setting/Test2"
import Test3 from "@/views/Test/Test3"
import Test4 from "@/views/Test/Test4"const router_items: RouteObject[] = [{path: "/",element: <MyLayout />,children: [{path: "",element: <Navigate to="/dashboard" />, // 重定向},{path: "dashboard",element: <Dashboard />,},{path: "project",element: <Project />,},{path: "setting",element: <Outlet />, // 占位符children: [{ path: "test1", element: <Test1 /> },{ path: "test2", element: <Test2 /> },],},{path: "test",element: <Outlet />, // 占位符children: [{ path: "test3", element: <Test3 /> },{ path: "test4", element: <Test4 /> },],},],},// 不需要layout的页面写到外面{path: "login",element: <Login />,},{ path: "*", element: <NotFound /> },
]export default () => {// 根据路由表生成对应的路由规则const ElementRouter = useRoutes(router_items)return ElementRouter
}

上述路由规则会在<MyLayout />中声明的位置处展示

在这里插入图片描述
APP中注册路由

// 路由
import GetRouter from "./router"function App() {const RouterElement = GetRouter()return <>{RouterElement}</>
}export default App

实现步骤

先创建高阶组件名为AuthRouter,并在main.tsx中引入并包裹APP。
高阶组件指接收一个组件并返回增强后的该组件。

AuthRouter

const AuthRouter = (props: { children: JSX.Element }) => {return props.children
}export default AuthRouter
import ReactDOM from "react-dom/client"
import App from "./App.tsx"
import "./index.scss"
// router
import { BrowserRouter as Router } from "react-router-dom"
import AuthRouter from "@/HOC/AuthRouter.tsx" // 高阶组件ReactDOM.createRoot(document.getElementById("root")!).render(<Router><AuthRouter><App /></AuthRouter></Router>
)

token相关

一、token失效重定向到login

AuthRouter

import { Navigate, useLocation } from "react-router-dom"const AuthRouter = (props: { children: JSX.Element }) => {const { pathname } = useLocation()let token = "sdnfowe623ognis"if (pathname === "/login") {return props.children}if (!token) {return <Navigate to="/login" replace />} else {return props.children}
}export default AuthRouter

二、白名单无需判断token

AuthRouter

import { Navigate, useLocation } from "react-router-dom"const AuthRouter = (props: { children: JSX.Element }) => {const { pathname } = useLocation()const whiteList = ["/login", "/test/test4"] // 声明白名单let token = "sdnfowe623ognis"// 白名单直接放行if (whiteList.includes(pathname)) {  return props.children}if (!token) {return <Navigate to="/login" replace />} else {return props.children}
}export default AuthRouter

权限相关

基本同白名单逻辑

AuthRouter

import { useLocation } from "react-router-dom"const AuthRouter = (props: { children: JSX.Element }) => {const { pathname } = useLocation()let auth_list = ["/login", "/dashboard"] // 权限只能访问这些路由if (!auth_list.includes(pathname)) {return (<div><h2>暂无权限</h2></div>)}return props.children
}export default AuthRouter

当访问无权路由时,展示如下:

在这里插入图片描述

每个页面都需要调用的函数

假如某些接口数据作用于全局且总会改变,如用户信息等,也可以写到AuthRouter中。
注意:只有处于登录态需要调用该函数的路由,才能调用。

AuthRouter

import { Navigate, useLocation } from "react-router-dom"
import API from "@/api"const AuthRouter = (props: { children: JSX.Element }) => {const { pathname } = useLocation()// 不需要获取用户信息的路由const notGetUserInfoRouteList: string[] = ["/login","/register","/test/test4",]let token = "dsnfoiwne23"if (!token) {return <Navigate to="/login" replace />} else {// 有token 且 需要调用if (!notGetUserInfoRouteList.includes(pathname)) {API.getUserInfo().then(({ code, data }) => {...})}return props.children}
}export default AuthRouter

上面的API是封装好的请求,具体可看另一篇文章:TS封装axios并约束请求参数以及响应的类型

整体代码

import { Navigate, useLocation } from "react-router-dom"
import cookie from "react-cookies"
import API from "@/api"const AuthRouter = (props: { children: JSX.Element }) => {const { pathname } = useLocation()const whiteList: string[] = ["/login", "/test/test4"] // 白名单(无需登录)const noUserInfoList: string[] = [...whiteList, "/register"] // 不需要调用 getuserinfo 的路由const authList: string[] = ["/login", "/dashboard"] // 权限只能访问这些路由if (!authList.includes(pathname)) {return (<div><h2>无权访问该页面</h2></div>)}// 如果当前路由不在白名单中,且没有 token,则重定向到登录页if (!whiteList.includes(pathname) && !cookie.load("token")) {return <Navigate to="/login" replace />}// 如果当前路由需要调用 getuserinfo 接口,就调用它if (!noUserInfoList.includes(pathname)) {API.getUserInfo().then(({ code, data }) => {...})}// 返回子组件return props.children
}export default AuthRouter

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/610898.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

idea 中运行spring boot 项目报 Command line is too long的解决办法。

Command line is too long 在这里选择edit configures 选择shrten command line , 选择 jar manifest 运行即可。

渗透测试实战——第一站

仅供交流学习使用&#xff0c;请勿用于非法用途 前言&#xff1a;刚学了sql注入&#xff0c;只听理论总感觉没啥用&#xff0c;今天花了一半个多小时&#xff0c;去尝试寻找有漏洞的网站&#xff0c;最终找到了一个&#xff1b;实践是检验真理的唯一标准。 我是通过黑客常用语法…

【vue】v-model 双向数据绑定

:value&#xff1a;单向数据绑定v-model&#xff1a;双向数据绑定 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">…

极狐GitLab对接OAuth2实现SSO

本文作者&#xff1a;极狐(GitLab) 高级解决方案架构师 武让 GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 企…

使用htmlentities()和nl2br()将文本数据正确显示到前台

问题&#xff1a; 在后台textarea里编辑了有一串字符串&#xff0c;虽然在textarea里编辑是有换行效果的&#xff0c;但是数据获取到就只是\n&#xff0c;前端是不认识这个的&#xff0c;正确输出到前台的换行只能是<br/>。 $str "ABCDEFGHIJKLMNOPQ"; echo…

lua学习笔记19(面相对象学习的一点总结)

print("*****************************面相对象总结*******************************") object{} --实例化方法 function object:new()local obj{}self.__indexselfsetmetatable(obj,self)return obj end-------------------------如何new一个对象 function object:…

【深度学习】Fine-Grained Face Swapping via Regional GAN Inversion高保真换脸范式

文章目录 代码介绍实践效果 帮助、问询 代码 https://github.com/e4s2022/e4s 介绍 Fine-Grained Face Swapping via Regional GAN Inversion 提出一种新的高保真换脸范式&#xff0c;能够保留期望的微妙几何和纹理细节。从微观面部编辑的角度重新思考换脸任务&#xff0c;基…

Web程序设计-实验02 CSS页面布局

【实验主题】 影视网站前台模板页设计 【实验任务】 1、浏览并分析多个影视网站&#xff08;详见参考资源&#xff0c;建议自行搜索更多影视网站&#xff09;的整体版面布局&#xff0c;对比同一网站不同页面&#xff08;主页、列表页、详情页&#xff09;的元素异同——剔除…

[Linux_IMX6ULL驱动开发]-驱动的分层及实现

目录 驱动分层的思路 驱动分层的实现 上层驱动的实现 次设备号的使用 上层驱动代码 底层驱动的实现 底层驱动c文件的实现 底层驱动头文件实现 应用层文件的实现 驱动分层的思路 在上一篇文章中&#xff0c;博主实现了通过寄存器控制引脚&#xff0c;以此来达到控制LE…

华为OD技术面试-爬楼计数(动态规划)

背景 2024-03-16 华为od 技术面试&#xff0c;记录题目和模型 题目 分析 入门级的 动态规划算法&#xff0c;直接写就行了 缓存递归 代码 DZs {} def climbStairs(n):if n<0:return 0if DZs.get(n, 0)>0 :return DZs[n]if n2:jf 2elif n1:jf 1;else:jf1 climb…

R语言绘制一次和二次相关性热图

在数据探索的过程中&#xff0c;我们往往会对数据与数据的相关性进行分析&#xff0c;例如我们常用的corrplot包&#xff0c;或者psych包中的corr.test函数&#xff0c;对两两变量间的相关性进行分析。我们常常会看到这样的相关性热图&#xff1a; 但有时变量间的关系并非线性…

systemctl start docker报错(code=exited, status=1/FAILURE)

运行systemctl start docker报错内容如下: 输入systemctl status docker.service显示以下内容&#xff1a; 本次启动不起来与docker服务无关 具体解决问题是修改 /etc/docker/daemon.json&#xff0c;vim /etc/docker/daemon.json # 添加如下内容 {"registry-mirrors&qu…