登录鉴权
我们把重点放在动态路由上,先简单过一遍登录鉴权流程:
(1)前端携带用户登录信息访问登录api
(2)登录api会对信息进行校验,校验失败会返回失败信息,校验成功就返回包含token的成功信息
(3)前端拿到token会将其保存起来(localStorage),这是登录
(4)那么用户的每次请求附带token,服务端就可以完成鉴权(判断有没有权限,什么样的权限)
动态路由
现在重点讲讲动态路由:
一般的后台数据库里面,就是分为一个user用户表,一个role权限路由表。在登录成功时,返回的成功信息包含routes信息,那么可以简单的分为用户和管理员两部分:
用户:
{
name: "普通用户",
avatar: "https://sf1-ttcdn-tos.pstatp.com/img/user-avatar/6364348965908f03e6a2dd188816e927~300x300.image",
desc: "普通用户 - people",
username: "people",
token: "4es8eyDwznXrCX3b3439EmTFnIkrBYWh",
routes: [
{ id: 1, name: "/", path: "/", component: "Layout", redirect: "/index", hidden: false, children: [
{ name: "index", path: "/index", meta: { title: "index" }, component: "index/index" },
]},
{ id: 2, name: "/form", path: "/form", component: "Layout", redirect: "/form/index", hidden: false, children: [
{ name: "/form/index", path: "/form/index", meta: { title: "form" }, component: "form/index" }
]},
{ id: 3, name: "/example", path: "/example", component: "Layout", redirect: "/example/tree", meta: { title: "example" }, hidden: false, children: [
{ name: "/tree", path: "/example/tree", meta: { title: "tree" }, component: "tree/index" },
{ name: "/copy", path: "/example/copy", meta: { title: "copy" }, component: "tree/copy" }
] },
{ id: 4, name: "/table", path: "/table", component: "Layout", redirect: "/table/index", hidden: false, children: [
{ name: "/table/index", path: "/table/index", meta: { title: "table" }, component: "table/index" }
] },
{ id: 6, name: "/people", path: "/people", component: "Layout", redirect: "/people/index", hidden: false, children: [
{ name: "/people/index", path: "/people/index", meta: { title: "people" }, component: "people/index" }
] }
]
}
管理员:
{
name: "管理员",
avatar: "https://sf3-ttcdn-tos.pstatp.com/img/user-avatar/ccb565eca95535ab2caac9f6129b8b7a~300x300.image",
desc: "管理员 - admin",
username: "admin",
token: "rtVrM4PhiFK8PNopqWuSjsc1n02oKc3f",
routes: [
{ id: 1, name: "/", path: "/", component: "Layout", redirect: "/index", hidden: false, children: [
{ name: "index", path: "/index", meta: { title: "index" }, component: "index/index" },
]},
{ id: 2, name: "/form", path: "/form", component: "Layout", redirect: "/form/index", hidden: false, children: [
{ name: "/form/index", path: "/form/index", meta: { title: "form" }, component: "form/index" }
]},
{ id: 3, name: "/example", path: "/example", component: "Layout", redirect: "/example/tree", meta: { title: "example" }, hidden: false, children: [
{ name: "/tree", path: "/example/tree", meta: { title: "tree" }, component: "tree/index" },
{ name: "/copy", path: "/example/copy", meta: { title: "copy" }, component: "tree/copy" }
] },
{ id: 4, name: "/table", path: "/table", component: "Layout", redirect: "/table/index", hidden: false, children: [
{ name: "/table/index", path: "/table/index", meta: { title: "table" }, component: "table/index" }
] },
{ id: 5, name: "/admin", path: "/admin", component: "Layout", redirect: "/admin/index", hidden: false, children: [
{ name: "/admin/index", path: "/admin/index", meta: { title: "admin" }, component: "admin/index" }
] },
{ id: 6, name: "/people", path: "/people", component: "Layout", redirect: "/people/index", hidden: false, children: [
{ name: "/people/index", path: "/people/index", meta: { title: "people" }, component: "people/index" }
] }
]
}
由此可以看出,routes就是admin管理员和people普通用户的差异化动态路由了,管理员多了一个admin的页面,而用户是没有的。
其实这里是有多种思路的。有些开发者喜欢完整的静态路由都在前端里面,然后根据router的meta属性,写上对应user的role,登录的时候,再根据后端返回的权限,去过滤比对权限,把该用户角色所对应的路由处理好,渲染处理,这也是主流的一种处理方式。这种就等于是把所有的路由和权限业务处理都放在了前端,一旦上线发布后,想要修改就需要重新打包处理,而且不能经由后台动态新增删除
const myRouter = new VueRouter({
routes: [{
path: '/login',
name: 'login',
meta: {
roles: ['admin', 'user']
},
component: () => import('@/components/Login')
},{
path: '/home',
name: 'home',
meta: {
roles: ['admin']
},
component: () => import('@/views/Home')
},{
path: '/404',
component: () => import('@/components/404')
}]
})
//假设通过接口从后台获取的用户角色,可以存储在token中
const role = 'user'
myRouter.beforeEach((to,from,next)=>{
if(to.meta.roles.includes(role)){
next() //放行
}else{
next({path:"/404"}) //跳到404页面
}
还有一种解法,就是所有的路由权限等,都交给后端,后端根据前端的账号密码,去获取角色权限,处理路由,丢出就是已经匹配对应角色的路由了。这种写法前端运算量不会太大,而且易于修改和后期维护以及动态的增删改查,本文就是以该种形式实现。
总体思路是
路由跳转上 后端根据权限返回route 前端持久化存储route 利用全局路由守卫将route数据进行动态添加addRoute 那么只要将没有的路由规则的url跳转到403页面就好
tml导航元素的显示上 没有路由权限的就不予显示。 因为前端持久化存储了route 那么可以进行一个route.include(‘xxx/xx’)的判断 如果有这个路由就显示,没有就不显示