Ant design pro v4 父路由对象不设置 authority
,子路由对象设置 authority
不生效bug?
例如有如下配置的路由👇
{
path: '/setting',
name: 'setting',
icon: 'SettingOutlined',
routes: [
{
path: '/setting/message',
name: 'message',
authority: ['user'],
component: './setting/user/Message',
dynamic: true,
},
{
path: '/setting/list',
name: 'account-list',
authority: ['admin'],
component: './setting/admin/AccountList',
dynamic: true,
}
]
}
触发场景:我登录的是 admin 权限的账号,我通过地址栏跳转到 /setting/message
,按配置来看,是跳转不成功的,但实际成功显示了。你们可以尝试一下。
当时陷入了深思,是我路由配错了吗?是配置写错了吗?然后回官网查看文档,是可以配置子路由的呀,又找前端的朋友看一下我的配置文件,演示一次给他看,他也懵逼了。😂😂😂
冒着脱发的危险,查看了他们的鉴权模块。
大概是这样子的:
// BasicLayout.jsx
// 当你访问一个路由时,它会在路由配置文件中返回与你访问路由匹配的路由对象
const authorized = getAuthorityFromRouter(props.route.routes, location.pathname || '/') || [{
authority: undefined,
}]
// 权鉴 props authority 就是传入到组件中进行鉴权,权限通过则显示,不通过则显示 noMatch 组件(props传入)
<Authorized authority={authorized.authorized} noMatch={noMatch}>
{children}
</Authorized>
然后一次偶然的 console.log(authorized.authorized)
发现了问题,(依旧是触发场景的操作)authorized
竟然返回来的是 undefined
(导致页面无需权限即可访问),明明我配置的权限是 ['user']
🤔🤔🤔
再往上console.log(authorized)
发现它返回的是 父路由 对象,就是 开头例子中那一整个对象。🤔
继续往上查阅 utils.js
中 getAuthorityFromRouter
方法,这个路由的功能就是 在路由配置文件中返回与你访问路由匹配的路由对象。问题就是出在这里了。🧐🧐🧐
因为这个方法,无论如何都是返回与你访问路由匹配的 父路由对象。就是你访问 /setting/message
这个路由,但返回的是 setting
整个路由,它上面是没有设置 authority
,这也导致后续的判断中,被判断为无需权限即可访问。
简单来说,它只会判断父路由对象上的 authority
,子路由 authority
无论是什么都不会生效。
你们可以尝试一下设置反例👇(发现 admin
账号都无法访问 setting
子路由,无论何种方式访问)
// 反例
{
path: '/setting',
name: 'setting',
icon: 'SettingOutlined',
authority: ['user'],
routes: [
{
path: '/setting/message',
name: 'message',
component: './setting/user/Message',
dynamic: true,
},
{
path: '/setting/list',
name: 'account-list',
component: './setting/admin/AccountList',
dynamic: true,
}
]
}
然后就只能...开战🙂🙂🙂
// utils.js
export const getAuthorityFromRouter = (router = [], pathname) => {
const authorityList = []
const route = router.find(
({
routes,
path = '/',
target = '_self'
}) => {
if (path && target !== '_blank' && pathRegexp(path).exec(pathname)) return true
const temp = getAuthorityFromRouter(routes, pathname)
if (routes && temp) {
temp.length && authorityList.push(temp)
return true
}
return false
}
);
// 计算权限并返回
if (route) {
// 如果之前就有无权限访问,直接拒绝
if (authorityList.includes('non')) return 'non'
let auth = route.authority
if (!auth) {
return authorityList.flat()
} else if (typeof auth === 'string') {
auth = [auth]
}
authorityList.unshift(auth)
// 取交集
const intersection = authorityList.reduce((total = [], a) => total.filter(item => a.includes(item)), authorityList[0])
console.log(intersection);
return intersection.length ? intersection : 'non'
}
return undefined
}
// BasicLayout.jsx
// 如果返回[]和undefined 都代表页面无需权限, non表示无权限访问该网页
let authorized = getAuthorityFromRouter(props.route.routes, location.pathname || '/');
authorized = authorized && authorized.length ? authorized : undefined
<Authorized authority={authorized} noMatch={noMatch}>
{children}
</Authorized>
nice!!!😛😛😛经过初步测试可以解决掉上面所有问题,虽然改写的代码丑陋了点(本人是一只菜鸡),哈哈哈。
如果大神有更好的解决方法,或者我理解有误可以到我的 GitHub 发邮件给我。