icestark
icestark copied to clipboard
[RFC]微应用权限控制的最佳实践
问题
子应用如果需要权限控制,一般会对 AppRoute 渲染进行劫持:
const AuthAppRoute = () => {
...
if (hasPermission && !fetchingAuth) {
return <AppRoute />;
} else {
return <NoPermission />;
}
}
由于每个路由切换都需要请求权限,在请求过程中或者没有权限时,显示无权限。 上述处理在路由切换的时候将会卸载子应用,导致每次应用重新挂载从而重复加载资源,希望官方需要提供类似场景的指引或者相关实现
背景
常见的菜单为结构的主从微前端类型,可以将微应用的权限控制转换为对菜单的权限控制。不过,仍存在以下问题:
- 通过直接链接可以访问到微应用
- 菜单的管控不等同于应用的管控,考虑多个菜单指向同一应用的场景:
目的
建立一致性的权限管控方案。
方案
修改后的方案 https://github.com/ice-lab/icestark/issues/396#issuecomment-964120096
流程示意图 https://github.com/ice-lab/icestark/issues/396#issuecomment-964828824
<AppRouter
AuthComponent: <AuthComponent />
// or
AuthComponent: (url, appConfig) => <AuthComponent />
>
</AppRouter>
这个配置有些问题,AppRouter
如何区分上下两种形式的 AuthComponent
auth 字段需要结合业务实际的场景,比如请求后端服务进行判断的方式
结合框架权限的方式,可以考虑结合 useAuth
的方式进行解构,不一定要耦合到 getApps 的方法中
<AppRouter AuthComponent: <AuthComponent /> // or AuthComponent: (url, appConfig) => <AuthComponent /> > </AppRouter>
这个配置有些问题,
AppRouter
如何区分上下两种形式的AuthComponent
修正为
import AuthComponent from './AuthComponent';
<AppRouter
AuthComponent: AuthComponent
>
</AppRouter>
刚好碰到这个问题 现在进度怎么样
我们的背景
- 页面分为『无需授权页(即直接访问不需要加载任何信息)』、『正常页面』、『无权限页面』
- 主应用通过getApps配置子应用的base路由
现在遇到问题
- 我们需要限制特定子应用中的路由,但是没找到好方法
首先,我们从后端拿到的权限配置是权限key,而不是具体的路径,所以我们需要有个路由路径和key的对照表 但是这个对照表不知道放在哪或者说不知道怎么获取子应用路由和key的匹配关系 我们现在是和menuConfig放在一起,但是感觉过于耦合,还会限制menu的一些功能 然后放在router.ts又不合适
- 不知道如何更好的和框架结合
首先,由于是微前端框架,所以没办法用ice本身的权限管理(auth+pageConfig),当然硬写理论上也可以
然后又由于我们会先判断是不是无需授权页面,所以可能没办法在getInitialData获取信息
@xmsz 上面的方案侵入性比较强,这两天会重新设计下。可以参与一起讨论下
背景
为尽量不耦合 Auth 方案,单独抽离一个 Auth 高阶组件,处理有关权限的逻辑。
方案
使用方式如下:
import { Auth } from '@ice/stark-auth';
<Auth
hasAuth={true}
// or
hasAuth = {(url: string) => return url.includes('seller')}
cache
NoAuthComponent: NoPermission
>
<AppRoute></AppRoute>
</Auth>
<Auth />
接受的参数:
-
hasAuth
,类型 boolean | Function 是否有权限 -
cache
是否根据 url 缓存权限状态。 -
NoAuthComponent
无权限时展示 -
PendingComponent
权限请求加载时渲染。
结合 build-plugn-icestark
import { Auth, AppRoute } from '@ice/stark';
const appConfig: AppConfig = {
icestark: {
type: 'framework',
getApps: () => {
// 根据 getInitialData 返回的 authData 来更新微应用配置信息
},
AppRoute: () => <Auth>AppRoute</Auth>
}
}
总结:
- 当第一次访问无权限的子应用页面,最佳的结果,不加载子应用,渲染一个无权限页面
- 当第一次访问子应用有权限的页面,正常加载应用。第二次访问无权限的页面,最佳的结果是,不重复加载子应用,渲染一个无权限页面。
第一类情况的降级用法,可以是先加载子应用,渲染一个无权限页面
第二个问题,无权限页由主应用,还是子应用提供。
- 主应用提供:切换过程中,可能会导致子应用重复加载
2. 子应用提供:对用户的接入不友好;如何触发子应用渲染无权限页;以及 Loading 页
结论: 在主应用集中式地处理权限,以及过渡状态。
● Auth 上需要设计 Loading 态的组件 ● 内部判定权限检测同步/异步,决定 loading 态是否呈现