轉轉統一許可權系統的設計與實現(後端實現篇)

語言: CN / TW / HK

一、許可權系統框架

如圖所示,許可權系統主要解決兩個問題: 1. 前端渲染:接入系統使用者登入後,獲取自己有許可權的選單,也就是前端sdk請求許可權系統獲取有許可權的選單並進行自動渲染。 1. 後端鑑權:使用者請求接入系統後端,拒絕沒有許可權的介面訪問,防止無許可權使用者獲取後端介面地址後直接訪問無許可權的介面。

為了解決這兩個問題,必然需要引入一些配套內容,其中重要的功能點如下:

  1. 使用者管理:統一登入系統,支撐許可權系統識別登入使用者。
  2. 許可權管理:系統管理、角色管理、選單管理、資料管理、角色人員繫結等功能,方便為使用者繫結相應的許可權。
  3. 後端鑑權:訪問接入系統介面呼叫時使用。

後面會一一介紹使用者管理、許可權管理、後端鑑權sdk的實現。

二、使用者管理

許可權系統支援轉轉、轉轉精神、發條愛客、自注冊四種來源的使用者資料,支援使用者在一個系統登入在其他系統保持登入狀態功能(統一登入),支援員工入職自動加入許可權系統(員工同步),這裡重點介紹統一登入。

2.1、統一登入

先從接入許可權的域名都是.zhuanspirit.com說起,統一登入利用瀏覽器攜帶Cookie特點:不同二級域名可以攜帶一級域名的Cookie。統一登入系統為接入系統種植一級域名Cookie,例如OA系統oa.zhuanspirit.com,許可權系統自身id.zhuanspirit.com統一種植域名為.zhuanspirit.com的Cookie,這樣OA、許可權系統等接入統一登入系統的系統就可以做到一處登入處處訪問。現在丟擲兩個問題: 1. 接入系統並未引入統一登入系統的任何程式碼,未登入使用者是怎樣跳轉到統一登入頁的? 1. 如何校驗Cookie是否合法的?

從以OA系統為例的圖中可以看出問題答案: 1. ngix會對*.zhuanspirit.com域名的請求做Cookie合法校驗,校驗不通過跳轉到登入頁,同時攜帶原url資訊。 1. 校驗合法性是通過Cookie的值是否和Redis中一致,不一致就需要重新登入。

三、許可權管理

轉轉許可權管理系統是一個基於經典RBAC許可權管理模型的實現,上圖為轉轉許可權系統的主要功能,本身實現複雜度並不高。但是由於歷史原因,轉轉許可權系統在實現的時候需要考慮相容原有許可權系統的資料,這是一個比較瑣碎複雜的事情,在這裡不做過多介紹。對於簡單的管理系統來說,靈魂在資料。對應到轉轉許可權系統,血肉就是管理UI,它的使命就是方便為資料表填充資料,具體一點就是為使用者表、系統表、選單表、資料表、角色表以及中間關係表填充資料。下面我就展現轉轉許可權系統的靈魂--資料庫表關係。 從上圖中可以看到轉轉許可權系統和RBAC一些差異:使用者直接可以與選單或者資料繫結,增加靈活性。

四、後端鑑權

4.1、工作原理

如上圖所示,後端鑑權sdk通過切面程式設計的思想,對請求url或者code進行攔截鑑權,如果登入使用者沒有許可權,則返回錯誤。

4.2、核心方法

java AuthResult res = authentication.check(new AppCodeAuthParmBuilder(APP_CODE, CODE, request)); 上面是sdk面向使用者的介面很容易可以看出來,進入非常簡單,僅僅需要三個引數:

  • APP_CODE:系統的系統編號
  • CODE:許可權編碼(可為空,為空時根據url鑑權)
  • request:HttpServletRequest(從中獲取Cookie資訊解析出登入使用者,以及url資訊判斷使用者是否有此url許可權)

4.3、使用demo

利用Spring Interceptor切面技術,下面是架構管理平臺關於ZZLock後臺操作的一個例子 ```java @Component public class ZZLockInterceptor implements HandlerInterceptor { @Resource private Authentication authentication; private static final String APP_CODE = "arch_ipms"; private static final String CODE = "ro_zzlock"; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

    AuthResult res = authentication.check(new AppCodeAuthParmBuilder(APP_CODE, CODE, request));

    if (res.isSuccess() && res.getCode() == ResultCodeEnum.SUCCESS.getCode()) {
        return true;
    } else {
        UserDTO user = authentication.parseUser(request);
        logger.info("選單 zzlock_get user {} 鑑權結果 code {} msg {}", user.getLoginName(), res.getCode(), res.getMsg());
        response.getWriter().write("user: " + user.getLoginName() + " no auth");
        response.getWriter().close();
    }

    return false;
}

} ```

五、總結

本篇文章著重介紹轉轉許可權系統的後端實現,從使用方的視角出發,也就是前端渲染和介面鑑權,引出轉轉許可權系統如何識別使用者(統一登入),如何儲存許可權資料(許可權管理),如何實現後端鑑權。

簡而言之,許可權系統的主要功能:許可權系統UI編輯許可權資料,使用者登入後,獲取配置好的選單和資料,並且校驗使用者訪問的後端介面。

轉轉研發中心及業界小夥伴們的技術學習交流平臺,定期分享一線的實戰經驗及業界前沿的技術話題。 關注公眾號「轉轉技術」,各種乾貨實踐,歡迎交流分享~