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 團隊再接再礪了。

相關文章
相關標籤/搜索