关于路由守卫
Vue中内置了路由守卫,包括全局路由守卫、组件路由守卫、独享路由守卫,其中全局路由守卫又包括前置路由守卫和后置路由守卫,但是React并没有封装简单的API供用户使用。
使用场景
例如一个网站需要有主页和登录页,正常的交互逻辑:用户首次打开网站进入登录页,登录成功后才能进入首页,但是假如不对用户的操作作权限控制,用户可以通过手动改变url的方式进入首页,这对此网站来说显然是不安全的。所以就需要使用路由守卫在每次路由跳转之前进行权限校验,如果校验通过才允许跳转,否则系统重定向至登录页或首页(根据项目实际需求确定)
代码实现
- Vue版本
文件: /src/router/router.ts
import { createRouter, createWebHistory, RouteRecordName } from 'vue-router'
import cookie from 'js-cookie'
import { staticRoutes, asyncRoutes } from './static'
// 路由表白名单
const allowList:RouteRecordName[] = ['login']
const loginRoute = '/login'
const indexRoute = '/'
const router = createRouter({
history: createWebHistory(),
routes: [...staticRoutes, ...asyncRoutes],
scrollBehavior: ()=>{ return { top: 0 }},
})
router.beforeEach((to, from, next) => {
// 根据 token 对路由进行权限校验,需要和后端配合使用
// 这里的 token 一般是登陆成功之后拿到后端返回的 token 并通过 Cookie.set('token', token字符串, {
// expires: time_limit // 设置存放时间
// })设置
const token = cookie.get('token');
if (token && token !== 'undefined') {
// 有 token 的状态下禁止用户回到登录页,重定向到首页
if (to.path === loginRoute) {
next({ path: indexRoute });
} else {
// 其他路由均可正常跳转
next()
}
} else {
// 无 token 的状态下,如果要跳转的路由是白名单中的路由,正常跳转
if (allowList.includes(to.name || '')) {
next()
} else {
// 无 token 且非白名单,重定向至登录页
next({ path: loginRoute });
}
}
})
// 路由加载后
router.afterEach(() => {});
export default router;
最后在 main.ts 中引入
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App);
app.use(router).mount('#app')
- React版本
虽然React没有路由守卫,但是我们可以通过高阶组件实现相关功能,使用方法如下:- 在src/components/Auth下创建 AuthRoute.tsx 文件(位置可根据自己的习惯存放)
import React from 'react'
import {Navigate, useLocation} from "react-router-dom";
import Cookie from "js-cookie";
type RouteProps = {
children?: React.ReactNode
}
const loginRoute = '/login'
const indexRoute = '/'
// 路由表白名单
const allowList = ['/login', '/register']
const AuthRoute: React.FC<RouteProps> = (props) => {
const location = useLocation();
// children 为子组件
const {children} = props
// 根据 token 对路由进行权限校验,需要和后端配合使用
// 这里的 token 一般是登陆成功之后拿到后端返回的 token 并通过 Cookie.set('token', token字符串, {
// expires: time_limit // 设置存放时间
// })设置
let token = Cookie.get('token')
if (token && token !== 'undefined') {
// 有 token 的状态下禁止用户回到登录页,重定向到首页
if (location.pathname === loginRoute) {
return <Navigate to={indexRoute}></Navigate>
} else {
// 其他路由均可正常跳转
return <>{children}</>
}
} else {
// 无 token 的状态下,如果要跳转的路由是白名单中的路由,正常跳转
if (allowList.includes(location.pathname || '')) {
return <>{children}</>
} else {
// 无 token 且非白名单路由,重定向至登录页
return <Navigate to={loginRoute}></Navigate>
}
}
}
export default AuthRoute
- 在 App.tsx中引入并设置
// 引入路由表
import AppRouter from "@/router";
import {BrowserRouter} from 'react-router-dom';
// 引入实现路由鉴权的高阶组件
import AuthRoute from "@/components/Auth/AuthRoute";
const App = () => {
return (
<div className="App">
<BrowserRouter>
<AuthRoute>
<AppRouter/>
</AuthRoute>
</BrowserRouter>
</div>
)
}
export default App