🧑🎓 个人主页:SilenceLamb
📖 本章内容:【全局前置守卫】
🌳Gitee仓库地址:👉🏽全局前置守卫
一、获取用户信息
🍑存储用户信息
-
👉🏽 可以理解为变量
state: {
token: getToken(),
name: '',
avatar: '',
roles: [],
permissions: []
},
- 👉🏽 操作变量的mutations
mutations: {
SET_TOKEN: (state, token) => {
state.token = token
},
SET_NAME: (state, name) => {
state.name = name
},
SET_AVATAR: (state, avatar) => {
state.avatar = avatar
},
SET_ROLES: (state, roles) => {
state.roles = roles
},
SET_PERMISSIONS: (state, permissions) => {
state.permissions = permissions
}
},
- 👉 获取用户信息
// 获取用户信息
GetInfo({commit}) {
return new Promise((resolve, reject) => {
getInfo().then(res => {
const avatar = (res.data.user.avatar === "" || res.data.user.avatar == null) ? require("@/assets/images/profile.jpg") : res.data.user.avatar;
if (res.data.roles && res.data.roles.length > 0) { // 验证返回的roles是否是一个非空数组
commit('SET_ROLES', res.data.roles)
commit('SET_PERMISSIONS', res.data.permissions)
} else {
commit('SET_ROLES', ['ROLE_DEFAULT'])
}
commit('SET_NAME', res.data.user.userName)
commit('SET_AVATAR',avatar)
resolve(res)
}).catch(error => {
reject(error)
})
})
},
avatar: state => state.user.avatar,
userName: state => state.user.userName,
roles: state => state.user.roles,
permissions: state => state.user.permissions,
title: state => state.setting.title,
logo: state => state.setting.logo,
🍑 导航栏添加头像
- 👉🏽 添加用户名
<span class="user-name"> {{ userName }}</span>
- 👉🏽 添加头像
<img :src="avatar" class="user-avatar" alt="avatar">
二、退出管理系统
🕰️退出系统action
// 退出系统
LogOut({commit, state}) {
return new Promise((resolve, reject) => {
logout(state.token).then(() => {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
commit('SET_PERMISSIONS', [])
removeToken()
resolve()
}).catch(error => {
reject(error)
})
})
},
🕰️导航栏添加退出
<el-dropdown-menu slot="dropdown" class="user-dropdown">
<el-dropdown-item divided @click.native="logout">
<span style="display:block;">🍑Log Out</span>
</el-dropdown-item>
</el-dropdown-menu>
🕰️ 创建退出方法
async logout() {
await this.$store.dispatch('user/LogOut')
await this.$router.push(`/login?redirect=${this.$route.fullPath}`)
}
三、路由配置
// 公共路由
export const constantRoutes = [
{
path: '/login',
component: () => import('@/views/login/login'),
hidden: true
},
{
path: '/404',
component: () => import('@/views/error/404'),
hidden: true
},
{
path: '/401',
component: () => import('@/views/error/401'),
hidden: true
},
{
path: '/',
component: Layout,
redirect: '/index',
children: [
{
path: 'index',
component: () => import('@/views/index/index'),
name: 'Index',
meta: { title: '首页', icon: 'dashboard', affix: true }
}
]
},
{
path: '/system',
component: Layout,
name: 'System',
meta: { title: '系统管理', icon: 'dashboard', affix: true },
children: [
{
path: '/user',
component: () => import('@/views/system/user/index'),
name: 'User',
meta: { title: '用户管理', icon: 'el-icon-user', affix: true }
},
{
path: '/role',
component: () => import('@/views/system/role/index'),
name: 'User',
meta: { title: '角色管理', icon: 'el-icon-s-custom', affix: true }
},
]
},
]
四、全局前置守卫
import router from './router'
import store from './store'
import {Message} from 'element-ui'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import {getToken, removeToken} from '@/utils/token' // get token from cookie
const whiteList = ['/login'] // no redirect whitelist
//全局钩子函数
//在跳转之前执行
router.beforeEach(async (to, from, next) => {
const hasToken = getToken()
if (hasToken) {
if (to.path === '/login') {
// if is logged in, redirect to the home page
next({path: '/'})
} else {
// determine whether the user has obtained his permission roles through getInfo
const hasRoles = store.getters.roles && store.getters.roles.length > 0
if (hasRoles) {
next()
} else {
try {
await store.dispatch('user/GetInfo')
next({...to, replace: true})
} catch (error) {
removeToken();
Message.error(error || 'Has Error')
next(`/login?redirect=${to.path}`)
}
}
}
} else {
if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
next(`/login?redirect=${to.path}`)
}
}
})
router.afterEach(() => {
NProgress.done()
})
-
首先调用 getToken 方法,这个方法实际上是去 Cookie 中拿认证 Token,也就是登录成功后后端返回给前端的那个 JWT 字符串。
- 如果 getToken 方法有返回值,说明用户已经登录了,那么进入到 if 分支中
- 如果 getToken 没拿到值,说明用户未登录,未登录的话,又分为两种情况:
- i:访问的目标地址处于免登录白名单中,那么此时直接访问即可;
- ii:访问的目标地址不在白名单中,那么此时就跳转到登录页面去,跳转的时候同时携带一个 redirect 参数,这样方便在登录成功之后,再跳转回访问的目标页面
-
如果 getToken 拿到了值,说明用户已经登录了,此时又分情况:如果用户访问的路径是登录页面,那么就给他重定向到项目首页(也就是在已经登录的情况下,不允许用户再次访问登录页面);如果用户访问的路径不是登录页面,那么首先判断 vuex 中的 roles 是否还有值?如果有值,说明当前就是用户点击了一个菜单按钮进行跳转的,那么直接跳转就行了;如果没有值,说明用户是按了浏览器的刷新按钮或者是 F5 按钮刷新进行的页面跳转,那么此时首先调用 getInfo 方法(位于 src/store/modules/user.js 文件中)去服务端重新加载当前用户的基本信息、角色信息以及权限信息。
-
后期完成: 然后再调用GenerateRoutes方法(位于 src/store/modules/permission.js 文件中)去服务端加载路由信息,并将加载到的路由信息放入到 router 对象中(前提是这个路由对象不是一个 http 链接,就是普通的路由地址)。
-
🍎main.js引入
import './permission'
- 🍎路由的配置
- affix:可以随意命名
true: 需要检查用户是否已登录
{
path: 'index',
component: () => import('@/views/index/index'),
name: 'Index',
meta: { title: '首页', icon: 'dashboard', affix: true }
}
📢🌥️如果文章对你有帮助【关注👍点赞❤️收藏⭐】