由于element多用来做后端管理界面,所以这里给大家推荐一个用来做后端管理的element框架!(vue-element-admin)
直接进入主题:
1.对路由跳转进行判断,如果符合权限就允许,反之就不行
2.对跳转页面进行逻辑请求判断,就是页面数据需要一定的权限才能发送请求(这样需要后端人员给你做,个人感觉不太现实,后端估计想干你)
3.根据权限,动态生成对应的路由,什么权限拥有什么路由(vue-element-admin)就是这么做的,动态生成路由
常用方法一般都是:
----------- v-if + router.beforeEach() ----------
由于后端管理界面涉及到,对登陆用户的权限判断,可能做的好点的后端管理页面,要么把相对应的跳转事件进行隐藏或判断,或者把跳转页面进行隐藏,我之前也是这样做的,对跳转的路由按钮进行 v-if 判断,然后再在router.beforeEach()进行路由判断,这样就可以防止部分用户,根据请求地址来实现跳转
-------------对跳转的按钮事件进行权限判断-------------
这样就比第一种方法更直接,对跳转页面的路由事件,添加一个方法,然后根据权限判断,if和else,满足就跳转,不满足就return,如果想要提升一下用户体验度,就弹出一个消息提示框,说您暂无权限!这是不是更简单
这样的方法,最直观,最简单,也最方便!但是呢,用户体验度不是很好,而且权限是写死的,不具备灵活性,但是并不妨碍这是一种好方法!!
vue-element-admin根据权限动态生成路由的方式
学习了一下vue-element-admin这个后端管理框架后:我就觉得它的这种动态生成路由的方式很新颖,也很厉害,所以再踩了几个坑以后,就来记录一下
构建项目上:ts+vuex+cookie
思路:
第一步:
就是在你登陆以后,后端返回token,然后在请求成功的回调里面,又发送token去后端去获取当前用户的详细信息,信息中包括了你这名用户的权限,是否为管理员身份,还是次级管理员身份,然后将token存入cookie,将请求获取到的数据存入vuex!假设这个存储你权限的字段交roles,是个数组,类似:[’admin'] or ['Secondary']
第二步:
这里要说明的是,路由表中会定义两个路由表,一个为公共路由表,一个为动态路由表,公共路由表就是不需要权限也能去访问,动态路由表顾名思义就是需要权限去获取了!然后根据获取到你的权限之后,会根据roles中的字段,去遍历动态路由表中的对应的路由表,然后将符合条件的路由表保存起来
第三步:最后将获取到的符合权限的路由,合并到固定路由下面,通过router.addRouter(),当然了这里还是要用到router.beforeEach()去做路由判断,让权限更牢靠一点
具体实现方法:贴代码
获取用户信息和权限
import { VuexModule, Module, Mutation, Action, getModule } from 'vuex-module-decorators'
import { login,UserInfo } from '../../api/user'
import { getCookie,setCookie } from '../../utils/cookies'
import store from '@/store'
export interface usermodel{
username:string,
password:string,
token:string
}
@Module({ dynamic: true, store, name: 'user' })
class User extends VuexModule implements usermodel{
public username = ""
public password = ""
public token = getCookie('token') ||""
public roles:string[] = []
@Mutation
private SET_TOKEN(token:string){
this.token = token
}
@Mutation
private SET_ROLES(roles:string[]){
this.roles = roles
}
@Mutation
private SET_NAME(name:string[]){
this.roles = name
}
@Action
public async Login(userInfo:{username:string,password:string}){ //登陸獲取token
let { username,password } = userInfo
username = username.trim()
const data = await login({username,password})
const { token } = data as any
setCookie('token',token)
this.SET_TOKEN(token)
}
@Action
public async getUserinfo(){ //根據token去獲取登陸用戶個人信息,判斷個人權限
if(this.token == ""){
console.log('token不存在或者已过期')
}
const {data} = await UserInfo(this.token)
if(!data){
throw Error('未查到此用户,请重新登陆')
}
const { roles,name } = data
if(!roles || roles.length<=0){
throw Error('您不属于管理员范畴')
}
this.SET_ROLES(roles)
this.SET_NAME(name)
}
}
export const UserModel = getModule(User)
根据权限筛选对应路由
import { VuexModule,Module,Action,Mutation,getModule } from 'vuex-module-decorators'
import { asyncRoutes,constantRoutes } from '@/router'
import store from '@/store'
import { RouteConfig } from 'vue-router'
export interface IpermissionState{
routes:RouteConfig[],
dynamicRoutes: RouteConfig[]
}
const hasPermission = (roles:string[],route:RouteConfig)=>{ //判断动态路由中的meta中是否包含你当前用户的权限
if(route.meta && route.meta.roles) {
return roles.some(role => route.meta.roles.includes(role))
}else{
return true
}
}
export const filterAsyncRoutes = (routes:RouteConfig[],roles:string[]):any=>{ //递归查询出动态路由中符合当前用户权限的路由
const res:RouteConfig[] = []
routes.forEach(route => {
const r = { ...route }
if(hasPermission(roles,r)){
if(r.children){
r.children = filterAsyncRoutes(r.children,roles)
}
res.push(r)
}
});
}
@Module({ dynamic: true, store, name: 'permission' })
class Permission extends VuexModule implements IpermissionState{
public routes:RouteConfig[] = []
public dynamicRoutes:RouteConfig[] = []
@Mutation
private SET_ROLES(routes:RouteConfig[]){ //合并固定路由和动态路由
this.routes = constantRoutes.concat(routes) //合并之后的所有的路由
this.dynamicRoutes = routes //获取到的所有的动态的路由
}
@Action
public GenerateRoutes(roles: string[]) {
let accessedRoutes
if(roles.includes('admin')){ //判断是否为管理员,如果是管理员就不用筛选路由,直接全部给出
accessedRoutes = asyncRoutes
}else{
accessedRoutes = filterAsyncRoutes(asyncRoutes,roles) //如果是次级管理员,就筛选出符合次级管理员的路由
}
this.SET_ROLES(accessedRoutes)
}
}
export const PermissionModule = getModule(Permission)
将符合权限的路由添加到固定路由上
import router from './router'
import { Route } from 'vue-router'
import { UserModel } from './store/models/user'
import { PermissionModule } from './store/models/permission'
const whitelist = ['/login','/auth-redirect']
router.beforeEach(async(to:Route,form:Route,next:any)=>{
if(UserModel.token){
if(to.path === '/login'){
next({path:'/'})
}else{
if(UserModel.roles.length === 0){
try{
await UserModel.getUserinfo() //调用获取用户信息的方法
const roles = UserModel.roles
PermissionModule.GenerateRoutes(roles) //筛选出符合条件的路由
router.addRoutes(PermissionModule.dynamicRoutes) //添加路由
next({ ...to, replace: true }) //这是会清除浏览器中的历史记录
}catch(err){
return console.log(err)
}
}else{
next()
}
}
}else{
if(whitelist.indexOf(to.path) !== -1){
next()
}else{
next('/login')
}
}
})
实现方法可能有些绕,有兴趣的小伙伴可以去官网下载源码去看看!多敲个两遍就知道了