icestark icon indicating copy to clipboard operation
icestark copied to clipboard

[RFC]微应用权限控制的最佳实践

Open ClarkXia opened this issue 3 years ago • 11 comments

问题

子应用如果需要权限控制,一般会对 AppRoute 渲染进行劫持:


const AuthAppRoute = () => {
  ...
  if (hasPermission && !fetchingAuth) {
    return <AppRoute />;
  }  else {
    return <NoPermission />;
  }
}

由于每个路由切换都需要请求权限,在请求过程中或者没有权限时,显示无权限。 上述处理在路由切换的时候将会卸载子应用,导致每次应用重新挂载从而重复加载资源,希望官方需要提供类似场景的指引或者相关实现

ClarkXia avatar Sep 17 '21 10:09 ClarkXia

背景

常见的菜单为结构的主从微前端类型,可以将微应用的权限控制转换为对菜单的权限控制。不过,仍存在以下问题:

  • 通过直接链接可以访问到微应用
  • 菜单的管控不等同于应用的管控,考虑多个菜单指向同一应用的场景: image

目的

建立一致性的权限管控方案。

方案

修改后的方案 https://github.com/ice-lab/icestark/issues/396#issuecomment-964120096

流程示意图 https://github.com/ice-lab/icestark/issues/396#issuecomment-964828824

maoxiaoke avatar Oct 11 '21 12:10 maoxiaoke

<AppRouter
  AuthComponent: <AuthComponent />
 // or
  AuthComponent: (url, appConfig) => <AuthComponent />
>
</AppRouter>

这个配置有些问题,AppRouter 如何区分上下两种形式的 AuthComponent

SoloJiang avatar Oct 12 '21 02:10 SoloJiang

auth 字段需要结合业务实际的场景,比如请求后端服务进行判断的方式 结合框架权限的方式,可以考虑结合 useAuth 的方式进行解构,不一定要耦合到 getApps 的方法中

ClarkXia avatar Oct 12 '21 02:10 ClarkXia

<AppRouter
  AuthComponent: <AuthComponent />
 // or
  AuthComponent: (url, appConfig) => <AuthComponent />
>
</AppRouter>

这个配置有些问题,AppRouter 如何区分上下两种形式的 AuthComponent

修正为

import AuthComponent from './AuthComponent';

<AppRouter
  AuthComponent: AuthComponent
>
</AppRouter>

maoxiaoke avatar Oct 12 '21 03:10 maoxiaoke

刚好碰到这个问题 现在进度怎么样

我们的背景

  • 页面分为『无需授权页(即直接访问不需要加载任何信息)』、『正常页面』、『无权限页面』
  • 主应用通过getApps配置子应用的base路由

现在遇到问题

  • 我们需要限制特定子应用中的路由,但是没找到好方法

首先,我们从后端拿到的权限配置是权限key,而不是具体的路径,所以我们需要有个路由路径和key的对照表 但是这个对照表不知道放在哪或者说不知道怎么获取子应用路由和key的匹配关系 我们现在是和menuConfig放在一起,但是感觉过于耦合,还会限制menu的一些功能 然后放在router.ts又不合适

  • 不知道如何更好的和框架结合

首先,由于是微前端框架,所以没办法用ice本身的权限管理(auth+pageConfig),当然硬写理论上也可以

然后又由于我们会先判断是不是无需授权页面,所以可能没办法在getInitialData获取信息

xmsz avatar Nov 03 '21 03:11 xmsz

@xmsz 上面的方案侵入性比较强,这两天会重新设计下。可以参与一起讨论下

maoxiaoke avatar Nov 04 '21 04:11 maoxiaoke

背景

为尽量不耦合 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>
  }
}

maoxiaoke avatar Nov 09 '21 12:11 maoxiaoke

总结:

  1. 当第一次访问无权限的子应用页面,最佳的结果,不加载子应用,渲染一个无权限页面
  2. 当第一次访问子应用有权限的页面,正常加载应用。第二次访问无权限的页面,最佳的结果是,不重复加载子应用,渲染一个无权限页面。

第一类情况的降级用法,可以是先加载子应用,渲染一个无权限页面

maoxiaoke avatar Nov 10 '21 03:11 maoxiaoke

第二个问题,无权限页由主应用,还是子应用提供。

  1. 主应用提供:切换过程中,可能会导致子应用重复加载 2. 子应用提供:对用户的接入不友好;如何触发子应用渲染无权限页;以及 Loading 页

结论: 在主应用集中式地处理权限,以及过渡状态。

maoxiaoke avatar Nov 10 '21 03:11 maoxiaoke

maoxiaoke avatar Nov 10 '21 06:11 maoxiaoke

● Auth 上需要设计 Loading 态的组件 ● 内部判定权限检测同步/异步,决定 loading 态是否呈现

maoxiaoke avatar Nov 17 '21 08:11 maoxiaoke