Antd Pro的权限组件

前端实际上是很难有权限验证的,由于从安全的角度来讲,前端没有绝对的安全,攻击者老是能够修改前端的代码。对于 API 的权限能够由服务端保证,可是对于页面的权限可能就比较麻烦了。最好的方法固然仍是后端控制——也就是 NodeJs 的后端。若是不能达到这个安全级别的话(不过许多应用也不必),那么剩下的方法都没有什么太大区别,不过若是须要支持动态配置,就须要服务端路由。javascript

Antd Pro 权限路由

这一块算是 Antd Pro 的模板代码,由于 React Router 和 umi 并无对于权限流(workflow)的封装(虽然实现起来很简单)。umi 能够在配置中增长Routes字段来进入鉴权组件,Antd Pro 的Routes使用了本身实现的Authorized组件。前端

Antd Pro 增长了另外一个authority字段,用来判断每一个路由的权限。Antd Pro 团队应该准备把这里设置的很灵活,由于在checkPermissions里是能够接受 promise 的,可是在src/pages/Authorized里最终看到的getRouteAuthority的 ts 定义只接受stringstring[]。这也是有缘由的,我猜想是 umi 对配置里的 routeData 作了序列化,致使里面的函数丢失。若是须要写自定义的路由鉴权方式,可能须要从这个地方改起。java

Antd Pro 的权限组件在src/components/Authorized模块下。这个模块默认导出一个RenderAuthorize的高阶函数,分别接受Authorized组件和currentAuthority做为参数。这个高阶函数的做用在于根据传入的currentAuthority来解析(parse)当前用户的权限,其内部使用了一个CURRENT变量来缓存解析的结果,并暴露给模块外部使用,这样能够避免重复解析形成效率损失。git

咱们也能够不使用这个高阶函数,那样就会每次调用传入的权限获取方法(在 Antd Pro 里是getAuthority)。github

感受这里有一点乱的地方是把最终配置了getAuthorityAuthorized放在了utils里。我以为做为一个默认配置的实例,应当仍是放在原先的组件文件夹下比较好,比较有条理性。typescript

最后看一下在Pages里实际使用的Authorized组件。咱们能够看到它的 TypeScript 接口类型(话说有了 TypeScript 之后,看源代码真的方便许多):后端

type IAuthorizedType = React.FunctionComponent<AuthorizedProps> & {
  Secured: typeof Secured;
  check: typeof check;
  AuthorizedRoute: typeof AuthorizedRoute;
};
复制代码

这个组件的内容很简单,就是调用check来检查权限。这个check是对抽象出来的checkPermissions方法的再封装,本质上就是为了实现一个包裹当前权限的部分应用函数。前面也提到过,checkPermissions能够对各类类型的authority作支持(好比说函数),具体细节比较简单就不细说了。api

最终,这就是咱们在src/pages/Authorized里看到的封装:promise

<Authorized
  authority={getRouteAuthority(location.pathname, routes) || ''}
  noMatch={isLogin ? <Redirect to="/exception/403" /> : <Redirect to="/user/login" />}>
  {children}
</Authorized>
复制代码

全部的判断逻辑都在一个入口处实现。缓存

研究 Antd Pro 权限组件的初衷主要仍是一些特殊需求和中间偶尔出现的 bug。好比,一开始我遇到了登陆后重定向到登陆页面的 bug,分析了源代码以后,我发现主要缘由是由于CURRENT变量缓存了未登陆时的权限。解决方法也很简单,只要调用reloadAuthorized便可。其实文档里对此也提到了,不过没有很是明确的提出这个约定,因此我觉得 Antd Pro 会隐式的作这一步,结果是我想多了。

还有当我在 config 里设置路由时,对于和Routes同层的authority配置是无效的。不过这个属于 umi 读取配置的逻辑:

{
  path: '/',
  component: '../layouts/BasicLayout',
  Routes: ['src/pages/Authorized'],
  authority: ['admin', 'user'],
  routes: [
    // forms
    {
      path: '/form',
      icon: 'form',
      name: 'form'
    },
  ],
}
复制代码

总之,Antd Pro 就是对权限判断逻辑作了一层简单的封装,弥补 React Router 的不足。

改写 Antd Pro 权限存储

Antd Pro 默认将权限所有存储在前端(页面权限和用户权限)。Antd Pro 曾经有对后端路由的支持,它是经过一种插件模式,来修改 app 的 render 函数。但后来这部分被移除了,由于它的数据是基于 mock 的,通常服务器没有实现,就会报错。

api/auth_routes 这个已经严重影响到发布

这部分的过程都被我考古出来了……其实我以为保留挺好的,可是可能这就是社区对开源项目的影响吧……

在基于 token 的认证中,咱们能够从 jwt token 里提取当前的身份信息(注意到这并不安全),但没有必要。咱们能够直接根据当前用户的 token 来获得后端路由。我所理解的后端路由,前端仍然会有 config.ts 里的配置,由于像 component 不可能在后端作管理。

社区里有很多人想要实如今登陆后获取路由的模式,这主要是基于角色的路由实在比较简单。感受这是Antd Pro 目前还不成熟的体现。

目前 umi 提供的异步挂载路由的方式是经过插件机制来解决,感受并不能说是很是正式的(能用)。并且这个在 app.js 里,不能在登陆后处理。

最后,我本身的实现是在登陆的异步请求以后挂载路由,可是这只能经过g_routes全局变量来操做,感受也是不太正式,只能期待 umi 团队再接再砺了。

相关文章
相关标签/搜索