iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >React-Router(V6)的权限控制实现示例
  • 680
分享到

React-Router(V6)的权限控制实现示例

React-Router权限控制React-Router权限 2023-05-19 08:05:40 680人浏览 薄情痞子
摘要

目录接口权限页面权限1. 菜单权限2. 路由权限按钮权限参考在一个后台管理系统中,安全是很重要的。不光后端需要做权限校验,前端也需要做权限控制。 我们可以大致将权限分为3种: 接口权

在一个后台管理系统中,安全是很重要的。不光后端需要做权限校验,前端也需要做权限控制。 我们可以大致将权限分为3种: 接口权限页面权限按钮权限

在这当中,前端主要关注点则是页面权限按钮权限,而前端做这些的主要目的则是:

  • 禁止用户访问一些无权限访问的页面
  • 过滤不必要的请求,减少服务器压力

下面主要是思路的整理,以及一些核心实现

接口权限

接口权限一般是用户登录后,后端根据账号密码来认证授权,并颁发token或者session等来保存用户登录状态。

后续客户端请求一般是在header中携带token,后端通过对token进行鉴权是否合法来控制是否可以访问接口。

一般后台会通过用户的角色等来做对应的接口权限控制

而需要我们前端做的是在请求中携带好登录后回传的token,我们以axios为例

const instance = axiOS.create(config);
instance.interceptors.request.use(
  (request: any) => {
    request.headers["access_token"] = localStorage.getItem("access_token");
    return request;
  },
  (err) => {
    Promise.reject(err.response);
  }
);
instance.interceptors.response.use(
  (response) => {
    if (response.status !== 200) return Promise.reject(response.data);
    if (response.data.code === 401) {
      //token过期或者错误
      window.location.replace("/login");
    }
    return response.data.data;
  },
  (err) => {
    Promise.reject(err.response);
  }
);

页面权限

首先,我们先完成路由配置

src/routes/routes.tsx

export type RoutesType = {
  path: string;
  element: ReactElement;
  children?: RoutesType[];
};
const routers: RoutesType[] = [
  {
    path: "/login",
    element: <Login />,
  },
  {
    path: "/",
    element: <Home />,
  },
  {
    path: "/foo",
    element: <Foo />,
    children: [
      {
        path: "/foo/auth-button",
        element: <MyAuthButtonPage />,
      },
    ],
  },
  {
    path: "/protected",
    element: <Protected />,
  },
  {
    path: "/unauthorized",
    element: <UnauthorizedPage />,
  },
  // 配置404,需要放在最后
  {
    path: "/*",
    element: <NotFound />,
  },
];

然后是基于路由配置来生成对应的路由组件

src/routes/root.tsx

const Root = () => {
  // 创建一个有子节点的Route
  const CreateHasChildrenRoute = (route: RoutesType) => {
    return (
      <Route path={route.path} key={route.path}>
        <Route
          index
          element={
            <AuthRoute key={route.path} path={route.path}>
              {route.element}
            </AuthRoute>
          }
        />
        {route?.children && RouteAuthFun(route.children)}
      </Route>
    );
  };
  // 创建一个没有子节点的Route
  const CreateNoChildrenRoute = (route: RoutesType) => {
    return (
      <Route
        key={route.path}
        path={route.path}
        element={
          <AuthRoute path={route.path} key={route.path}>
            {route.element}
          </AuthRoute>
        }
      />
    );
  };
  // 处理我们的routers
  const RouteAuthFun = (routeList: any) => {
    return routeList.map((route: RoutesType) => {
      let element: ReactElement | null = null;
      if (route.children && !!route.children.length) {
        element = CreateHasChildrenRoute(route);
      } else {
        element = CreateNoChildrenRoute(route);
      }
      return element;
    });
  };
  return (
    <BrowserRouter>
      <Routes>{RouteAuthFun(routers)}</Routes>
    </BrowserRouter>
  );
};

最后是只需要在入口中写入Root组件即可

ReactDOM.createRoot(document.getElementById("root") as htmlElement).render(
  <Provider store={store}>
    <Root />
  </Provider>
);

上面只是完成了基本的配置,下面才是权限相关

路由权限主要分为两个方向:

1. 菜单权限

一般来说,后台通过维护userrolemenuuser_rolemenu_role这几张表来做相应的权限设计。

所以,在登录接口中,一般后台会返回用户对应的角色菜单等信息。我们通过redux-toolkit保存登录数据。大致信息如下(未真正请求接口,只写了初始数据):

src/pages/login/Login.slice.ts

interface LoginState {
  username: string;
  role: string;
  menuLists: any[];
}
// Define the initial state using that type
const initialState: LoginState = {
  username: "ryo",
  role: "admin",
  menuLists: [
    {
      id: "1",
      name: "首页",
      icon: "icon-home",
      url: "/",
      parent_id: "0",
    },
    {
      id: "2",
      name: "foo",
      icon: "icon-foo",
      url: "/foo",
      parent_id: "0",
    },
    {
      id: "2-1",
      name: "auth-button",
      icon: "icon-auth-button",
      url: "/foo/auth-button",
      parent_id: "2",
    },
  ],
};

这里的role表示当前用户的角色,menuLists为用户可访问的菜单

然后在首页中生成菜单列表

const getMenuItem = (menus: any): any => {
  return menus.map((menu: any) => {
    if (menu.children) {
      return (
        <div key={menu.url}>
          <Link to={menu.url}>{menu.name}</Link>
          {getMenuItem(menu.children)}
        </div>
      );
    }
    return (
      <div key={menu.url}>
        <Link to={menu.url}>{menu.name}</Link>
      </div>
    );
  });
};
function genMenu(array: any, parentId = "0") {
  const result = [];
  for (const item of array) {
    if (item.parent_id === parentId) {
      const menu = { ...item };
      menu.children = genMenu(array, menu.id);
      result.push(menu);
    }
  }
  return result;
}
function Home() {
  const menuLists = useAppSelector((state) => state.login.menuLists);
  const menuTree = genMenu(menuLists);
  return (
    <div>
      <h1>home page</h1>
      {getMenuItem(menuTree)}
    </div>
  );
}
export default Home;

但是,只根据权限列表来动态生成菜单并不能完全实现权限相关的目的。用户还可以通过在地址栏输入url的方式来访问没有在菜单中显示的页面。

2. 路由权限

我们可以通过实现一个AuthRoute来解决上述的问题。

通过AuthRoute来拦截页面的访问操作。

src/routes/AuthRoute.tsx

// 无需权限认证的白名单
// 一般是前端的一些报错页
const DONT_NEED_AUTHORIZED_PAGE = ["/unauthorized", "/*"];
const AuthRoute = ({ children, path }: any) => {
  // 该flag用于控制 受保护页面的渲染时机,需要等待useEffect中所有的权限验证条件完成后才表示可以渲染
  const [canRender, setRenderFlag] = useState(false);
  const navigate = useNavigate();
  const menuLists = useAppSelector((state) => state.login.menuLists);
  const menuUrls = menuLists.map((menu) => menu.url);
  const token = localStorage.getItem("access_token") || "";
  // 在白名单中的无需验证,直接跳转
  if (DONT_NEED_AUTHORIZED_PAGE.includes(path)) {
    return children;
  }
  useEffect(() => {
    // 用户未登录
    if (token === "") {
      message.error("token 过期,请重新登录!");
      navigate("/login");
    }
    // 已登录
    if (token) {
      // 已登录需要通过loGout来控制退出登录或者是token过期返回登录界面
      if (location.pathname == "/login") {
        navigate("/");
      }
      // 已登录,根据后台传的权限列表做判断
      if (!menuUrls.includes(location.pathname)) {
        navigate("/unauthorized", { replace: true });
      }
    }
    // 当上面的权限控制通过后,再渲染受保护的页面
    setRenderFlag(true);
  }, [token, location.pathname]);
  if (!canRender) return null;
  return children;
};
export default AuthRoute;

然后,在我们生成Route的时候在element属性中使用AuthRoute,这一步,我们已经在上面src/routes/root.tsx这个文件中写进去了。

到这里,我们就通过实现AuthRoute来拦截页面访问,做权限相关处理。

然后我们可以运行该仓库 代码来看效果。

目前没有实现登录相关功能,所以需要手动在localStorage中添加access_token来模拟登录。

  • 如果没有登录(没有access_token)或者登录已过期,访问任何路由都会被路由到/login
  • 如果已经登录,但是再访问登录页面,会被路由到/首页
  • 如果已经登录,但是访问了一个你无访问的页面,如/protected,则会被路由到/unauthorized页面

按钮权限

按钮级别的权限,根据当前用户角色的不同,可以看到的按钮和操作不同。这里我只简单实现了一个AuthButton

src/coponents/auth-button/index.tsx

import { Button } from "antd";
import type { ButtonProps } from "antd";
import React from "react";
import { useAppSelector } from "../../hooks/typedHooks";
interface AuthButtonProps extends ButtonProps {
  roles: string[];
}
const AuthButton: React.FC<AuthButtonProps> = ({ roles, children }) => {
  const role = useAppSelector((state) => state.login.role);
  if (roles.includes(role)) {
    return <Button>{children}</Button>;
  }
  return null;
};
export default AuthButton;

使用方法如下,新增了一个roles属性,表示哪些角色可以看见该按钮

src/pages/foo/auth-button.tsx

const ButtonPermission: React.FC = () => {
  const role = useAppSelector((state) => state.login.role);
  return (
    <div>
      <h1>Button Permission</h1>
      <AuthButton roles={["admin", "user"]}>添加</AuthButton>
      <AuthButton roles={["admin"]}>编辑</AuthButton>
      <AuthButton roles={["admin"]}>删除</AuthButton>
    </div>
  );
};
export default ButtonPermission;

我们可以手动的修改Login.slice.ts中的role来查看不同的情况。

这种实现方式比较简单,大伙可以根据自己的具体场景选择更好的方案

参考

  • 认证、授权、鉴权和权限控制
  • segmentfault.com/a/1190000020887109

到此这篇关于React-Router(V6)的权限控制实现示例的文章就介绍到这了,更多相关React-Router权限控制内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: React-Router(V6)的权限控制实现示例

本文链接: https://www.lsjlt.com/news/212626.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • React-Router(V6)的权限控制实现示例
    目录接口权限页面权限1. 菜单权限2. 路由权限按钮权限参考在一个后台管理系统中,安全是很重要的。不光后端需要做权限校验,前端也需要做权限控制。 我们可以大致将权限分为3种: 接口权...
    99+
    2023-05-19
    React-Router权限控制 React-Router权限
  • react-router v6实现权限管理+自动替换页面标题的案例
    目录权限管理总结学了一段时间的react+ts,想着写一个项目练练手,由于初次写react+ts项目,有很多东西并不知道应该怎么写,再加上之前写vue项目的习惯,突然转换react有...
    99+
    2023-05-20
    react-router v6权限 react-router v6页面标题
  • 使用vue-router实现动态权限控制的示例分析
    这篇文章将为大家详细讲解有关使用vue-router实现动态权限控制的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。使用vue开发带权限管理系统,尤其是采用了vu...
    99+
    2024-04-02
  • vue-router如何实现权限控制
    这篇文章主要讲解了“vue-router如何实现权限控制”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“vue-router如何实现权限控制”吧!在vue-router控制前端权限是常见需求:...
    99+
    2023-07-04
  • React 组件权限控制的实现
    目录前话正文1. 控制方式1.1 直接计算1.2 通用权限Hoc1.3 权限包裹组件2. 控制结果2.1 显隐控制2.2 自定义渲染3. 权限数据3.1 静态权限3.2 动态权限前话...
    99+
    2024-04-02
  • react-router-dom v6 通过outlet实现keepAlive 功能的实现
    本文主要介绍了react-router-dom v6 通过outlet实现keepAlive 功能的实现,具体如下: keepAlive代码: import React, { us...
    99+
    2024-04-02
  • vue实现菜单权限控制的示例代码
    大家在做后台管理系统时一般都会涉及到菜单的权限控制问题。当然解决问题的方法无非两种——前端控制和后端控制。我们公司这边的产品迭代速度较快,所以我们是从前端控制路由迭代到后端控制路由。...
    99+
    2024-04-02
  • 如何使用vue-router实现动态权限控制
    本篇内容介绍了“如何使用vue-router实现动态权限控制”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!使用vue开发带权限管理系统,尤其...
    99+
    2023-07-04
  • 基于vue,vue-router, vuex及addRoutes进行权限控制的示例分析
    这篇文章将为大家详细讲解有关基于vue,vue-router, vuex及addRoutes进行权限控制的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。基于vue...
    99+
    2024-04-02
  • MyBatis-Plus拦截器实现数据权限控制的示例
    目录前言背景上代码(基础版)进阶版前言背景 平时开发中遇到根据当前用户的角色,只能查看数据权限范围的数据需求。列表实现方案有两种,一是在开发初期就做好判断赛选,但如果这个需求是中途加...
    99+
    2023-02-24
    MyBatis-Plus 权限控制 MyBatis-Plus 拦截器权限控制
  • vue-router如何实现路由懒加载和权限控制
    本篇内容主要讲解“vue-router如何实现路由懒加载和权限控制”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“vue-router如何实现路由懒加载和权限控制”吧!1、为什么要使用路由懒加载呢...
    99+
    2023-07-04
  • vue-router中怎么实现路由懒加载和权限控制
    今天就跟大家聊聊有关vue-router中怎么实现路由懒加载和权限控制,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1、为什么要使用路由懒加载呢用v...
    99+
    2024-04-02
  • Spring Security实现统一登录与权限控制的示例代码
    目录项目介绍统一认证中心配置授权服务器配置WebSecurity登录菜单鉴权资源访问的一些配置有用的文档项目介绍 最开始是一个单体应用,所有功能模块都写在一个项目里,后来觉得项目越来...
    99+
    2024-04-02
  • RBAC权限控制的实现原理
    本篇内容介绍了“RBAC权限控制的实现原理”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! ...
    99+
    2024-04-02
  • React使用Context与router实现权限路由详细介绍
    目录前言思路实现向根组件注入权限列表抽离ContextHOC实现权限路由组件实现实现使用方法实现类似react-router-config的集中式权限路由配置实现使用方法前言 之前使...
    99+
    2023-01-28
    React权限路由 React Context权限路由 React router权限路由
  • mysql 中怎么实现权限控制
    本篇文章给大家分享的是有关mysql 中怎么实现权限控制,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。概述mysql权限控制在不同的上下文和不...
    99+
    2024-04-02
  • vue路由权限和按钮权限的实现示例
    目录一 菜单路由权限二 按钮权限的实现一 菜单路由权限 1.1前端路由配置表 1.2后端数据返回 1.3 拿到数据后存到vuex  1.4 扁平化的目的是为了跳转路由...
    99+
    2024-04-02
  • Spring Security权限管理实现接口动态权限控制
    目录摘要前置知识数据库设计数据库表结构数据库表介绍ums_adminums_roleums_admin_role_relationums_menuums_resourceums_re...
    99+
    2024-04-02
  • SpringBoot Security权限控制自定义failureHandler实例
    目录创建hander文件夹修改WebSecurityConfig配置创建hander文件夹 在 java 源码目录下创建hander文件夹, 在该文件夹下创建CustomAuthen...
    99+
    2022-11-16
    SpringBoot Security failureHandler SpringBoot Security
  • Openresty如何实现的网关权限控制
    小编给大家分享一下Openresty如何实现的网关权限控制,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!技术栈本小节采用了以下的技术栈:Openresty(lua...
    99+
    2023-06-19
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作