怎么在Vue中实现权限控制

这期内容当中小编将会给大家带来有关怎么在Vue中实现权限控制,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

一、前言

怎么在Vue中实现权限控制

1、接口访问的权限控制

2、页面的权限控制

  • 菜单中的页面是否能被访问

  • 页面中的按钮(增、删、改)的权限控制是否显示

下面我们就看一看是如何实现这些个权限控制的。

二、接口访问的权限控制

接口权限就是对用户的校验。正常来说,在用户登录时服务器需要给前台返回一个Token,然后在以后前台每次调用接口时都需要带上这个Token,然后服务端获取到这个Token后进行比对,如果通过则可以访问。

现有的做法是在登录成功的回调中将后台返回的Token直接存储到sessionStorage,然在请求时将Token取出放入headers中传给后台,代码如下:

this.$http({
method:'get',
url:'test/query?id=20',
withCredentials:true,
headers:{
token:sessionStorage.getItem('token'),
name:sessionStorage.getItem('name')//应后台需求传的用户名
}
}).then(response=>{
//请求成功后的操作
})

后来在一些文章中发现axios可以在拦截器中直接将Token塞入config.headers.Authorization中,作为全局传入。下面是代码部分:

//main.js
importaxiosfrom'axios'

//实例化Axios,并进行超时设置
constservice=axios.create({
timeout:5000
})
//baseURL
//axios.defaults.baseURL='https://api.github.com';

//httprequest拦截器
//每次请求都为http头增加Authorization字段,其内容为token
service.interceptors.request.use(
config=>{
if(store.state.user.token){
config.headers.Authorization=`token${store.state.user.token}`;
}
returnconfig
},
err=>{
returnPromise.reject(err)
}
);
exportdefaultservice

三、页面权限控制

在前面已经说到,页面权限控制又分为两种:

  • 1菜单中的页面是否能被访问

  • 2页面中的按钮(增、删、改)的权限控制是否显示

这些权限一般是在固定页面进行配置,保存后记录到数据库中。

按钮权限暂且不提,页面访问权限在实现中又可以分为两种方式:

  • 1显示所有菜单,当用户访问不在自己权限内的菜单时,提示权限不足

  • 2只显示当前用户能访问的权限内菜单,如果用户通过URL进行强制访问,则会直接进入404

既然展现出来后不能点,那算几个意思,逗我玩儿呢?所谓眼不见为净,综合考虑后,肯定是方案二比较符合良好的用户体验。

好,我们现在梳理一下大致的页面访问权限的流程:

在这里插入图片描述

在对流程梳理完成后我们开始进行详细的编写。

1、创建路由表

创建路由表实际上没有什么难度,照着vue-router官方文档给的示例直接写就行了。但是因为有部分页面是不需要访问权限的,所以需要将登录、404、维护等页面写到默认的路由中,而将其它的需要权限的页面写到一个变量或者一个文件中,这样可以有效的减轻后续的维护压力。

下面将index.js的代码贴上,异步路由将适量减少,以免占过多篇幅。

//router/index.js
importVuefrom'vue'
importRouterfrom'vue-router'
importAppfrom'@/App'
importstorefrom'../store/index'

Vue.use(Router);

//手动跳转的页面白名单
constwhiteList=[
'/'
];
//默认不需要权限的页面
constconstantRouterMap=[
{
path:'/',
name:'登录',
component:(resolve)=>require(['@/components/login'],resolve)
},
{
path:'/index',
name:'nav.Home',
component:(resolve)=>require(['@/components/index'],resolve)
},
{
path:'/templateMake',
name:'模板制作',
component:(resolve)=>require(['@/components/Template/templateMake'],resolve)
},
{
path:'/programMack',
name:'节目制作',
component:(resolve)=>require(['@/components/Template/programMack'],resolve)
},
{
path:'/release',
name:'节目发布',
component:(resolve)=>require(['@/components/Program/release'],resolve)
}
]

//注册路由
exportconstrouter=newRouter({
routes:constantRouterMap
});

//异步路由(需要权限的页面)
exportconstasyncRouterMap=[

{
path:'/resource',
name:'nav.Resource',
meta:{
permission:[]
},
component:(resolve)=>require(['@/components/Resource/resource'],resolve)
},
{
path:'/template',
name:'nav.Template',
meta:{
permission:[]
},
component:(resolve)=>require(['@/components/Template/template'],resolve)
},
{
path:'/generalSet',
name:'nav.System',
meta:{
permission:[]
},
component:(resolve)=>require(['@/components/SystemSet/generalSet'],resolve)
},
{
path:'',
name:'nav.Log',
component:App,
children:[
{
path:'/userLog',
name:'nav.UserLog',
meta:{
permission:[]
},
component:(resolve)=>require(['@/components/Log/userLog'],resolve),
},
{
path:'/operatingLog',
name:'nav.SystemLog',
meta:{
permission:[]
},
component:(resolve)=>require(['@/components/Log/operatingLog'],resolve),
},
]
}
]
];

注意事项:这里有一个需要非常注意的地方就是 404 页面一定要最后加载,如果放在constantRouterMap一同声明了404,后面的所以页面都会被拦截到404,详细的问题见addRoutes when you've got a wildcard route for 404s does not work

2、页面访问权限

在开始时我们梳理了一个大致的页面访问权限流程。下面我们先实现最核心的部分

我们首先获取用户权限列表,在这里我们将接触到vuex状态管理,官方文档有详细介绍,这里就不过多描述了,下面请看代码:

//store/index.js
importAxiosfrom'axios'
importVuefrom'vue'
importVuexfrom'vuex'

Vue.use(Vuex);
constaxios=Axios.create();

conststate={
mode:'login',
list:[]
};

constgetters={};

constmutations={
setMode:(state,data)=>{
state.mode=data
},
setList:(state,data)=>{
state.list=data
}
};

constactions={
//获取权限列表
getPermission({commit}){
returnnewPromise((resolve,reject)=>{
axios({
url:'/privilege/queryPrivilege?id='+sessionStorage.getItem('privId'),
methods:'get',
headers:{
token:sessionStorage.getItem('token'),
name:sessionStorage.getItem('name')
}
}).then((res)=>{
//存储权限列表
commit('setList',res.data.cust.privileges[0].children);
resolve(res.data.cust.privileges[0].children)
}).catch(()=>{
reject()
})
})
}
};

exportdefaultnewVuex.Store({
state,
mutations,
actions,
getters
})

好了,我们现在请求后台拿到了权限数据,并将数据存放到了vuex中,下面我们需要利用返回数据匹配之前写的异步路由表,将匹配结果和静态路由表结合,开成最终的实际路由表。

其中最关键的是利用vue-router2.2.0版本新添加的一个addRoutes方法,我们看看官方文档如何解释此方法的:

router.addRoutes(routes) 2.2.0+

动态添加更多的路由规则。参数必须是一个符合 routes 选项要求的数组。

那我们现在就可以开始使用addRoutes进行路由匹配了。下面看代码:

//router/index.js
/**
*根据权限匹配路由
*@param{array}permission权限列表(菜单列表)
*@param{array}asyncRouter异步路由对象
*/
functionrouterMatch(permission,asyncRouter){
returnnewPromise((resolve)=>{
constrouters=[];
//创建路由
functioncreateRouter(permission){
//根据路径匹配到的router对象添加到routers中即可
permission.forEach((item)=>{
if(item.children&&item.children.length){
createRouter(item.children)
}
letpath=item.path;
//循环异步路由,将符合权限列表的路由加入到routers中
asyncRouter.find((s)=>{
if(s.path===''){
s.children.find((y)=>{
if(y.path===path){
y.meta.permission=item.permission;
routers.push(s);
}
})
}
if(s.path===path){
s.meta.permission=item.permission;
routers.push(s);
}
})
})
}

createRouter(permission)
resolve([routers])
})
}

然后我们编写导航钩子

//router/index.js
router.beforeEach((to,form,next)=>{
if(sessionStorage.getItem('token')){
if(to.path==='/'){
router.replace('/index')
}else{
console.log(store.state.list.length);
if(store.state.list.length===0){
//如果没有权限列表,将重新向后台请求一次
store.dispatch('getPermission').then(res=>{
//调用权限匹配的方法
routerMatch(res,asyncRouterMap).then(res=>{
//将匹配出来的权限列表进行addRoutes
router.addRoutes(res[0]);
next(to.path)
})
}).catch(()=>{
router.replace('/')
})
}else{
if(to.matched.length){
next()
}else{
router.replace('/')
}
}
}
}else{
if(whiteList.indexOf(to.path)>=0){
next()
}else{
router.replace('/')
}
}
});

到这里我们已经完成了对页面访问的权限控制,接下来我们来讲解一下操作按扭的权限部分。

四、数据操作权限

是否还记得前面的路由配置中我们多出来的一个代码,下面我们拿出来看看:

//异步路由(需要权限的页面)
exportconstasyncRouterMap=[

{
path:'/resource',
name:'nav.Resource',
meta:{
permission:[]
},
component:(resolve)=>require(['@/components/Resource/resource'],resolve)
},
{
path:'/template',
name:'nav.Template',
meta:{
permission:[]
},
component:(resolve)=>require(['@/components/Template/template'],resolve)
},
{
path:'/generalSet',
name:'nav.System',
meta:{
permission:[]
},
component:(resolve)=>require(['@/components/SystemSet/generalSet'],resolve)
},
{
path:'',
name:'nav.Log',
component:App,
children:[
{
path:'/userLog',
name:'nav.UserLog',
meta:{
permission:[]
},
component:(resolve)=>require(['@/components/Log/userLog'],resolve),
},
{
path:'/operatingLog',
name:'nav.SystemLog',
meta:{
permission:[]
},
component:(resolve)=>require(['@/components/Log/operatingLog'],resolve),
},
]
}
]
];

为每个路由页面增加meta字段。在routerMatch函数中将匹配到的详细权限字段赋值到这里。这样在每个页面的route对象中就会得到这个字段。

asyncRouter.find((s)=>{
if(s.path===''){
s.children.find((y)=>{
if(y.path===path){
//赋值
y.meta.permission=item.permission;
routers.push(s);
}
})
}
if(s.path===path){
s.meta.permission=item.permission;
routers.push(s);
}
})

接下来我们编写一个vue自定义指令对页面中需要进行鉴权的元素进行判断,比如类似这样的:

<a@click="upload"v-allow="'3'"></a>/*3代表一个上传权限的ID,权限中有3则显示按钮*/

我们直接注册一个全局指令,利用vnode来访问vue的方法。代码如下:

//main.js
//按扭权限指令
Vue.directive('allow',{
inserted:(el,binding,vnode)=>{
letpermissionList=vnode.context.$route.meta.permission;
if(!permissionList.includes(binding.value)){
el.parentNode.removeChild(el)
}
}
})

上述就是小编为大家分享的怎么在Vue中实现权限控制了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注恰卡编程网行业资讯频道。

发布于 2021-04-15 01:55:49
收藏
分享
海报
0 条评论
165
上一篇:使用Python3怎么批量重命名文件 下一篇:怎么在Flutter中自定义Plugin
目录

    0 条评论

    本站已关闭游客评论,请登录或者注册后再评论吧~

    忘记密码?

    图形验证码