Ant design pro v4 鉴权不生效bug
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
,按配置来看,是跳转不成功的,但实际成功显示了。你们可以尝试一下。
当时陷入了深思,是我路由配错了吗?是配置写错了吗?然后回官网查看文档,是可以配置子路由的呀,又找前端的朋友看一下我的配置文件,演示一次给他看,他也懵逼了。😂😂😂
冒着脱发的危险,查看了他们的鉴权模块。
大概是这样子的:
// 当你访问一个路由时,它会在路由配置文件中返回与你访问路由匹配的路由对象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, } ]}
然后就只能…开战🙂🙂🙂
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}
// 如果返回[]和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 发邮件给我。