前言
前端路由守卫鉴权涉及的内容很多。本文主要介绍的是vue
和react
框架的 登录路由守卫鉴权过程,即登录之后才能进入系统的某些页面,没登录成功话需要重定向到登录页,这种形式的拦截鉴权基本上每个系统都会有这样的需求。
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')
总结
- 在
React
中,实现路由守卫鉴权的核心就是将每个路由组件使用高阶组件
进行包裹,在这个高阶组件里面进行权限相关逻辑的判断。 - 在
Vue
中,实现路由守卫鉴权的核心就是通过使用vue-router
自身提供的beforeEach
全局前置守卫。
原文链接:https://juejin.cn/post/7342501848412733467 作者:阿镇吃橙子