途牛原創|途牛無線權限系統的架構設計與實踐

以前寫過一篇大話權限中心的PHP架構之道,主要是從軟件工程角度介紹,如何經過編碼規範、依賴管理、數據源架構、事務處理、單元測試等技術,來保障權限系統的高可用,並未真正的涉及這套系統的架構。php

今天準備從設計細節上分享一二。編程

望各位看官,心有「空杯」,帶着「問題」一探究竟。架構

0. RBAC3

這裏仍是尤其的重要,由於他是整套系統設計的根基app

因此殘忍的從上一篇中複製了一遍。。。單元測試

RBAC認爲權限受權其實是Who、What、How的問題。在RBAC模型中,who、what、how構成了訪問權限三元組,也就是「Who對What(Which)進行How的操做」。測試

  • Who:權限的擁用者或主體(如Principal、User、Group、Role、Actor等等)this

  • What:權限針對的對象或資源(Resource、Class)。編碼

  • How:具體的權限(Privilege,正向受權與負向受權)。url

  • Operator:操做。代表對What的How操做。也就是Privilege+Resourcespa

  • Role:角色,必定數量的權限的集合。權限分配的單位與載體,目的是隔離User與Privilege的邏輯關係.

RBAC3模型

權限系統的本質就是這個模型(我的觀點勿噴)。咱們在此核心思想上,抽象了兩個新概念。

應用建模、權限自治

下面將從如下4個層面展開介紹。

  • 應用建模

  • 業務場景

  • 權限管理

  • 鑑權設計

1. 應用建模

系統架構上支撐權限系統靈活配置,不僵硬字段,不僵硬行爲,基於各類業務權限管控的特徵靈活設計。

公式一枚:應用=資源+行爲+角色

1.1 字段定義

簡單點說,就是要管控資源的屬性和行爲

好比要管控菜單,屬性就包括菜單ID、菜單名稱、菜單URL、菜單ICON、上級菜單ID等,行爲就包括訪問、受權等。(菜單權限)

好比要管控城市,屬性就包括區域ID、區域名稱、區域代碼、所屬區域ID等,行爲就包括訪問、受權等。(區域權限)

好比要管控CMS,字段就包含頁面ID、頁面名稱等,行爲就包括訪問、受權、編輯、重置等。(CMS數據權限)

按照慣性的思惟,這裏就是3張資源表對應角色表,同時還有3張資源角色關係表,換而言之,就是有多少資源須要管控就有多少張表(又是我的觀點,勿噴)。

慣性的思惟,兩個痛點

  1. 每一種資源都要獨立存儲。

  2. 每一種資源都要有一套Form排版&交互&存儲實現。

爲了解決這個問題,咱們作了如下的設計。

字段建模

任意資源的字段,均可以抽象成以下幾類。

  • 資源映射字段(mapField)

  • 資源節點字段(treeFiled)

  • 資源系統字段(systemFields)

  • 資源表單字段(columns)

  • 資源行爲字段(privileges)

舉個栗子:菜單資源。

class menu extends app
{
    public static $appMapField = 'url';
    public static $appTreeField = 'name';
    public static $columns = array(
        array(
            'id' => 'id',
            'label'  => '菜單ID',
            'type'  => 'input',
            'format' => 'int',
            'option' => array()
        ),
        array(
            'id' => 'name',
            'label'  => '菜單名稱',
            'type'  => 'input',
            'format' => 'string',
            'option' => array()
        )
    );
    public static $privileges = array(
        array(
            'id'    => 'access',
            'name'  => '訪問'
        )
    );
    public static $systemFields = array('id', 'parent_id');
}

動態表單

表單在網頁中主要負責數據採集功能。一個表單有三個基本組成部分:

  1. 表單標籤;

  2. 表單域,包含了文本框、密碼框、隱藏域、多行文本框、複選框、單選框、下拉選擇框和文件上傳框等;

  3. 表單按鈕。

常規工做是靜態表單

設計動態表單模型,基本的思路應該是數據和表現顯示的分離。拋開表現層,一個表單包含的若干個字段和填寫的數據。所謂動態,就是這些字段名稱可能改變,數量可能有增減。

  • 經過資源的columns字段控制表現層。

  • 經過資源的數據字段控制數據層。

經過這種模式,任意資源的Form排版&交互&存儲都動態實現了。

1.2 數據存儲

資源表對應的Schema以下:

字段名稱 字段備註
應用ID /
資源ID /
資源父ID /
資源Data JSON

經過反射API,獲取當前應用的資源存儲插件(資源Data字段)。

app::find($params['app_id'])->getResoucePlugin()->save($params['data']);

經過資源基類作數據存儲的統一封裝。

public function save()
{
    $this->beforeSave($this->attributes);
}

protected function beforeSave()
{
    //check attributes
}

很顯然資源Data字段,不能很好的完成單資源行爲鑑權的任務。

設計上引入了資源映射字段,每當資源變動時,觸發addMap,會同步字段信息到資源映射關係表中(資源的語義化索引)。

舉幾個栗子,方便你們理解這個字段:

  • 好比菜單類應用,映射字段就是菜單連接。

  • 好比數據類應用,映射字段就是數據ID。

public function addMap()
{
    if ($this->map) {
        //sync map field
    } else {
        //create map field
    }
}

應用建模,相對來講是一個較技術的話題,換個方向,下面來和你們聊一聊系統的業務場景。

2. 業務場景

系統架構上支撐多種業務形態的權限管控。

2.1 菜單類業務

說到權限,大多數應用場景都會想到菜單權限,然而咱們也不例外,菜單類的應用,就是生產的第一個實例。

舉個栗子:A系統/菜單權限應用

  • 字段

    • 菜單ID、菜單名稱、菜單連接、菜單上級ID

  • 行爲

    • 訪問、受權

2.2 數據類業務

數據類應用,相對於菜單類型來講,更關注的是,對某一行數據的行爲控制,行爲是多樣的。

舉個栗子:A數據/數據權限應用

  • 字段

    • 數據ID、數據名稱

  • 行爲

    • 訪問、受權、編輯、刪除、新增、重置、導出、導入

2.3 表單類業務

表單類應用,在2B的系統中,權限設計尤其重要。

舉個栗子:A確認單/表單權限應用

  • 字段

    • 模塊ID、模塊名稱(行程模塊、供應商模塊、訂單模塊、財務模塊)

  • 行爲

    • 訪問、受權、只讀、可寫、隱藏

總結一下權限的業務場景:

  • 菜單類:單資源的單行爲(可否」行爲「當前「資源」)

  • 數據類:單資源的多行爲

  • 表單類:多資源的多行爲

小夥伴們,大家的業務場景能實現嗎?(留言吧)

3 權限管理

接下來講說權限管理中的一些設計之道。

3.1 自治

設計上參考JIRA,當前應用的管理者主導當前應用的權限生態

  • 資源的增刪改查

  • 角色的增刪改查

  • 資源字段定義

  • 資源行爲定義

  • 資源行爲的角色賦予

3.2 自舉

系統中給每一種資源都天生賦予一種系統行爲叫作「受權」。

任意資源節點的角色行爲賦予,都由擁有該資源節點受權行爲的角色去分配。

3.3 雙向受權

兩個維度受權,方便檢索,也方便配置。

基於角色+行爲,選擇資源。

基於資源+行爲,選擇角色。

^^^^^^^^

下一個階段將會支持默認權限的配置,非應用內的角色,也一樣能夠享有應用內的部分資源的部分行爲的權限。

4 鑑權設計

最後簡單說下,鑑權接口的設計。

U、R、P、S分別表示用戶集合、角色集合、許可權集合和會話集合。

PA P×R表示許可權與角色之間多對多的指派關係。

UA U×R表示用戶與角色之間多對多的指派關係。

公式一枚:S=UA ∩ PA

4.1 單應用+單行爲

統稱爲資源樹接口。

舉個栗子:R角色在A應用中擁有P行爲的資源。

4.2 單應用+單資源+單行爲

統稱爲行爲鑑權接口。

舉個栗子:R角色在A應用中是否擁有R資源的P行爲。

結束語

權限系統一直以來是咱們應用系統不可缺乏的一個部分,若每一個應用系統都從新對系統的權限進行設計,以知足不一樣系統用戶的需求,將會浪費咱們很多寶貴時間,因此花時間來設計一個相對通用的權限系統是頗有意義的。

設計一個相對通用的系統是頗有意義的。(不只僅是權限)

多交流,多分享,書寫更好的代碼。

享受編程和技術所帶來的快樂。

相關文章
相關標籤/搜索