前端框架对比系列之vue和react的登录路由守卫鉴权

前言

前端路由守卫鉴权涉及的内容很多。本文主要介绍的是vuereact框架的 登录路由守卫鉴权过程,即登录之后才能进入系统的某些页面,没登录成功话需要重定向到登录页,这种形式的拦截鉴权基本上每个系统都会有这样的需求。

1. react-router-dom 5.x.x 的路由守卫鉴权

对于react框架,我们常用的路由插件 React-Router-dom,话不多说,基于已有的基础初始化项目工程,我们展开讨论。

1.1 定义 routes

基于现有的项目工程,我们新建文件目录 router,在该目录下新建文件 routes.js,在 meta 里面可以定义我们需要的元数据,比如说是否需要登录、网页标题等等。

import Home from "../pages/Home";
import About from "../pages/About";
import Login from "../pages/Login";

const routes = [
  {
    path: "/home",
    component: Home,
    meta: {
      title: "首页",
      needLogin: false, // 不需要登录就可以打开页面
    },
  },
  {
    path: "/about",
    component: About,
    meta: {
      title: "关于",
      needLogin: true, // 需要登录后菜可以打开页面
    },
  },
  {
    path: "/login",
    component: Login,
    meta: {
      title: "登录",
      needLogin: false, // 不需要登录就可以打开页面
    },
  },
  {
    path: '/',
    redirect: '/home'
  },
];

export default routes;

1.2 定义一个路由组件 auth.js

在文件目录 router中新建一个路由组件 auth.js, 该组件的作用是实现路由的拦截逻辑:

import { Route, Redirect } from "react-router-dom";
function Auth(props) {
  const {
    component: Component,
    path,
    meta,
    routes,
    redirect,
    exact,
    strict,
  } = props;

  // 设置网页标题
  if (meta && meta.title) {
    document.title = meta.title;
  }

  // 重定向
  if (redirect) {
    return <Redirect to={redirect} />;
  }

  // 判断是否需要登录
  if (meta && meta.needLogin) {
    const token = localStorage.getItem("react-demo-token");
    // 没登录去登录页
    if (!token) {
      return <Redirect to="/login" />;
    }
  }

  return (
    <Route
      path={path}
      exact={exact}
      strict={strict}
      render={(props) => <Component {...props} routes={routes} />}
    ></Route>
  );
}

export default Auth;

1.3 在根组件根据routes配置来渲染Auth组件

如下图所示,对于前端单页面应用项目,需要在主页名提供一个渲染区域,该区域通过不同的url路径,映射生成不同的页面,即我们所说的路由渲染过程:

/* eslint-disable no-unused-vars */
import { ConfigProvider } from 'antd';
import routes from "./router/routes";
import { Switch } from "react-router-dom";
import Auth from './router/auth';

function App() {
  return (
    <ConfigProvider theme={{ token: { colorPrimary: '#ff721f' } }}>
      <div className="App">
        <div className='app-tab' style={{ borderBottom: 'solid 1px grey' }}>
          <h1>react 首页导航</h1>
        </div>
        {/* 路由渲染区域 */}
        <Switch>
          {routes.map((route) => {
            return (
              // 路由鉴权
              <Auth key={route.path} {...route}></Auth>
            );
          })}
        </Switch>
      </div>
    </ConfigProvider>
  );
}

export default App;

必须在入口文件index.js中使用 BrowserRouter 组件:

import { BrowserRouter } from "react-router-dom";

ReactDOM.createRoot(document.getElementById("root")).render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

2. vue-router 3.x.x 的路由守卫鉴权

vue2 中使用的路由主要是vue-router 3.x.x,该路由插件内置了七个路由守卫,对于路由拦截相关需求,基本上不需要我们额外开发,但是在实际开发过程中,对于前端鉴权这块,我们基本上使用 beforeEach 全局前置守卫就能满足基本需求开发。

2.1 定义 routes

首先我们定义好系统的路由,对于非首页组件可以使用路由懒加载。在 meta 里面可以定义我们需要的元数据,比如说是否需要登录、网页标题等等。基于现有的项目工程,我们新建文件目录 router,在该目录下新建文件 routes.js

import Home from "../components/Home.vue"

const routes = [
  {
    path: '/',
    redirect: '/home'
  },
  {
    path: "/home",
    name: "home",
    component: Home,
    meta: {
      needLogin: false, // 不需要登录
      title: "首页"
    }
  },
  {
    path: "/login",
    name: "login",
    component: () => import(/* webpackChunkName: "login" */ "../components/Login.vue"), // 路由懒加载
    meta: {
      needLogin: false, // 不需要登录
      title: "登录"
    }
  },
  {
    path: "/about",
    name: "about",
    component: () => import(/* webpackChunkName: "about" */ "../components/About.vue"), // 路由懒加载
    meta: {
      needLogin: true, // 需要登录
      title: "关于"
    }
  }
];

export default routes;

2.2 实例化 router,并定义路由守卫逻辑

创建好路由后就定义路由拦截的逻辑了。主要通过 beforeEach 全局前置守卫。这里的核心逻辑就是判断前往的页面是否需要登录,需要登录就进一步判断当前系统是否有token,有就进入页面,没有就重定向到登录页。

import VueRouter from "vue-router";
import routes from "./routes"
import Vue from 'vue';

Vue.use(VueRouter);

const router = new VueRouter({
  mode: "hash",
  routes,
});

router.beforeEach((to, from, next) => {
  // 判断是否需要登陆
  if (to.meta.needLogin) {
    const token = localStorage.getItem("vue2-demo-token");
    if (token) {
      next();
    } else {
      next("/login");
    }
  } else {
    // 不需要登录则直接放行
    next();
  }
});

// 全局后置守卫可以修改标题
router.afterEach((to, from) => {
  if (to.meta.title) {
    document.title = to.meta.title;
  }
});

export default router;

2.3 配置路由的入口

在首页 App.vue中添加标签 router-view,即路由跳转区域。

<template>
  <div id="app">
    <div class="app-tab">
      <h3>vue2 首页导航</h3>
    </div>
    <router-view></router-view>
  </div>
</template>

在主文件入口处引用 router 实例:

import router from './router'

new Vue({
  router,
  render: h => h(App),
}).$mount('#app')

3. vue-router 4.x.x 的路由守卫鉴权

vue3 中使用的路由主要是vue-router 4.x.x,该路由插件内置了6个路由守卫,对于路由拦截相关需求,基本上不需要我们额外开发,但是在实际开发过程中,对于前端鉴权这块,我们基本上使用 beforeEach 全局前置守卫就能满足基本需求开发。

// 全局前置守卫
beforeEach(to, from, next) 
// 全局解析守卫
beforeResolve(to, from, next) 
// 路由守卫
beforeEnter(to, from, next) 
// 组件内守卫(更新)
onBeforeRouteUpdate(to, from, next) 
// 组件内守卫(离开)
onBeforeRouteLeave(to, from, next) 
// 全局后置守卫
afterEach(to, from) 

3.1 定义 routes

首先我们定义好系统的路由,对于非首页组件可以使用路由懒加载。在 meta 里面可以定义我们需要的元数据,比如说是否需要登录、网页标题等等。基于现有的项目工程,我们新建文件目录 router,在该目录下新建文件 routes.js

import Home from "../components/Home.vue"

const routes = [
  {
    path: '/',
    redirect: '/home'
  },
  {
    path: "/home",
    name: "home",
    component: Home,
    meta: {
      needLogin: false, // 不需要登录
      title: "首页"
    }
  },
  {
    path: "/login",
    name: "login",
    component: () => import(/* webpackChunkName: "login" */ "../components/Login.vue"), // 路由懒加载
    meta: {
      needLogin: false, // 不需要登录
      title: "登录"
    }
  },
  {
    path: "/about",
    name: "about",
    component: () => import(/* webpackChunkName: "about" */ "../components/About.vue"), // 路由懒加载
    meta: {
      needLogin: true, // 需要登录
      title: "关于"
    }
  }
];

export default routes;

3.2 实例化 router,并定义路由守卫逻辑

创建好路由后就定义路由拦截的逻辑了。主要通过 beforeEach 全局前置守卫。这里的核心逻辑就是判断前往的页面是否需要登录,需要登录就进一步判断当前系统是否有token,有就进入页面,没有就重定向到登录页。

import { createRouter, createWebHistory , createWebHashHistory} from "vue-router";
import routes from "./routes"

const router = createRouter({
  history: createWebHashHistory(), // hash 模式
  routes,
});

router.beforeEach((to, from, next) => {
  // 判断是否需要登陆
  if (to.meta.needLogin) {
    const token = localStorage.getItem("vue3-demo-token");
    if (token) {
      next();
    } else {
      next("/login");
    }
  } else {
    // 不需要登录则直接放行
    next();
  }
});

// 全局后置守卫可以修改标题
router.afterEach((to, from) => {
  if (to.meta.title) {
    document.title = to.meta.title;
  }
});

export default router;

3.3 配置路由的入口

在首页 App.vue中添加标签 router-view,即路由跳转区域。

<template>
  <div id="app">
    <div class="app-tab">
      <h3>vue2 首页导航</h3>
    </div>
    <router-view></router-view>
  </div>
</template>

在主文件入口处引用 router 实例 ( 此处要注意vue3 和 vue2 框架引用的差异 ):

import router from './router'
import { createApp } from 'vue'

const app = createApp(App);
app.use(router);
app.mount('#app')

总结

  1. React中,实现路由守卫鉴权的核心就是将每个路由组件使用 高阶组件 进行包裹,在这个高阶组件里面进行权限相关逻辑的判断。
  2. 在 Vue 中,实现路由守卫鉴权的核心就是通过使用 vue-router 自身提供的 beforeEach 全局前置守卫。

原文链接:https://juejin.cn/post/7342501848412733467 作者:阿镇吃橙子

(0)
上一篇 2024年3月5日 上午11:15
下一篇 2024年3月5日 下午4:05

相关推荐

发表回复

登录后才能评论