Ant design pro v4 鉴权不生效bug

Ant design pro v4 鉴权不生效bug

Feb 09, 2023 ·
4 Min Read

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.jsgetAuthorityFromRouter 方法,这个路由的功能就是 在路由配置文件中返回与你访问路由匹配的路由对象。问题就是出在这里了。🧐🧐🧐

因为这个方法,无论如何都是返回与你访问路由匹配的 父路由对象。就是你访问 /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 发邮件给我。

Last edited Feb 15