1. 程式人生 > 實用技巧 >多公司許可權模型

多公司許可權模型

為什麼80%的碼農都做不了架構師?>>> hot3.png

此文轉自我的個人部落格:http://www.weicms.net/2012/12/17/quanxian.html

今天和一個網友爭論了許可權的問題,我感覺有必要分享下我的研究心得.

許可權 無非是 角色 人員 資源 的配比關係

許可權的操作無非是 增刪改查,匯入,匯出 的操作,以及針對資料集的操作

業務結構無非是 公司,部門,使用者

在rest時代,許可權無非是 對一個URL是否有許可權操作! 許可權的本質就是URL的訪問控制!

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

-- ----------------------------

-- Table structure for `users`

-- 都是常用的欄位

-- ----------------------------

DROPTABLEIF EXISTS `users`;

CREATETABLE`users` (

`id`varchar(40)NOTNULL,

`name`varchar(50)DEFAULTNULL,

`userCode`varchar(50)NOTNULL,

`password`varchar(50)NOTNULL,

`email`varchar(100)DEFAULTNULL,

PRIMARYKEY(`id`)

) ENGINE=InnoDBDEFAULTCHARSET=utf8;

---角色表

---角色是繼承關係

---level,roleCode為表示層級關係,部門表類似.主要用於快速查詢,拋棄遞迴函式.

DROPTABLEIF EXISTS `role`;

CREATETABLE`role` (

`id`varchar(50)NOTNULLDEFAULT'',

`pid`varchar(50)NOTNULLDEFAULT'',--父角色ID

`roleName`varchar(200)NOTNULL,

`level`intNOTNULLDEFAULT0,--角色處的層級,根角色為1,它的子角色為2 孫角色為3

`roleCode`varchar(200)NOTNULL,--根角色001 他的子角色為001001,001002...孫角色為001001001,001002001....依次類推.

PRIMARYKEY(`id`)

) ENGINE=InnoDBDEFAULTCHARSET=utf8;

-- ----------------------------

-- Table structure for `model`

-- ----------------------------

DROPTABLEIF EXISTS `model`;

CREATETABLE`model` (

`id`varchar(50)NOTNULL,

`modelName`varchar(200)NOTNULL,

PRIMARYKEY(`id`)

) ENGINE=InnoDBDEFAULTCHARSET=utf8;

----

-- ----------------------------

-- Table structure for `re_user_role`使用者角色中間表

-- ----------------------------

DROPTABLEIF EXISTS `re_user_role`;

CREATETABLE`re_user_role` (

`id`varchar(50)NOTNULL,

`userId`varchar(50)NOTNULL,

`roleId`varchar(50)NOTNULL,

PRIMARYKEY(`id`)

) ENGINE=InnoDBDEFAULTCHARSET=utf8;

--角色資源中間表

DROPTABLEIF EXISTS `re_role_model`;

CREATETABLE`re_role_model` (

`id`varchar(50)NOTNULL,

`roleId`varchar(50)NOTNULL,

-- `startDate` datetime,

-- `endDate` datetime,--表示許可權的生存週期,用於領導臨時分配許可權,這裡簡化暫不討論

-- allunit int,--主要用於判斷是否級聯下級部門,這裡不討論

`pageurl`varchar(1000)NOTNULL,

`bool`int(11)NOTNULLDEFAULT'1',--表示真假,0為假,1為真

PRIMARYKEY(`id`)

) ENGINE=InnoDBDEFAULTCHARSET=utf8;

基本表結構如此,其他例如 unit 什麼的這裡就不寫了

說下場景,借用網友的一張圖片啊
154119_GsbS_724215
這裡要重點說下 re_user_model 中間表的pageurl 和bool欄位

pageurl是一個正則表示式,用於匹配使用者訪問的URL . bool表示真假,前提是pagurl必須匹配.

pageurl 和model表也沒有直接關係了,只是一個正則表示式而已.

如果pagurl匹配時, bool=0表示不可訪問,bool=1表示可以訪問此url.例如 角色superuser 能夠訪問除了/admin/開頭之外的所有url.就可以在資料庫插入兩條資料

1

2

INSERTINTO`re_role_model`VALUES('b1156249-9a8c-4f71-99ca-f56864401c41','superuser','(.*)','1');

INSERTINTO`re_role_model`VALUES('fa1f2c33-b5b8-4134-ae50-53334de61fc3','superuser','.*/admin/.*','0');

根據 bool欄位正序查詢

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

String model_sql="SELECT re.* FROM re_role_model as re,re_user_role as rerole

where

re.roleId=rerole.roleId and rerole.userId=:userId order by re.bool asc";

//對比url是否匹配

booleanflag=false;

for(Re_Role_Model m:models){

String pageurl=m.getPageurl();

Integer bool=m.getBool();

Pattern pattern = Pattern.compile(pageurl);

Matcher matcher = pattern.matcher(requestURL);//請求的url是否具有許可權

booleanf=matcher.matches();

if(f&&(bool==0)){//如果沒有許可權,跳出.

flag=false;

break;

}

if(f&&(bool==1)){

flag=true;

break;

}

}

returnflag;

這是整個控制的核心 訪問的url是根據正則匹配的!! 通過rest 將資料許可權轉變成對URL的訪問控制

系統依賴rest實現許可權的控制

約定url如下 : /{model}/{operation}/{公司ID}/ 為標準開頭

操作約定為 save/delete/update/get/import/export

我認為 公司擁有單獨的組織結構,可以認為是根,所以單獨列出.當然也可以根據業務需要去掉{公司ID}

例如 /user/update/abc/unit789/123 (/user/update/{公司ID}/{部門ID}/{userID})意義為 修改 abc公司下部門為unit789 id為123的員工資訊

所有的角色都是從根角色派生而來(可以根據業務實際需要決定是否角色繼承),根角色為 admin(超級管理員) 其他的角色都是依次派生 就和主管分配許可權是一致的. 例如 superuser 派生自admin

1

2

insert into role values('admin','','超級管理員','1','001')

insert into role values('superuser','admin','超級使用者','2','001001')

主管操作是一樣的,這個其實使用者前臺操作比較複雜,後臺理順關係還是比較簡單的.每個使用者都可以從自己的許可權範圍內分給其他使用者(其實也是角色,只是後臺預設生成了)

關於re_role_model 中的 allunit 主要是用來判斷是否包含子部門

例如 admin給 superuser分配了.*/user/get/gs123/unitabc/.* (/user/get/{公司ID}/{部門ID}) 用來判斷 superuser是否能夠查詢 unitabc下的所有子部門 如果unitabc下的部門較少 可以用多條記錄代替 例如

..*/user/get/gs123/unitabc1/.* .*/user/get/gs123/unitabc2/.* 如果子部門較多 可以啟用 allunit 欄位,根據實際情況自行判斷吧

pageurl正則表示式,反轉獲得實際許可權資料 可 以擴充套件實現資料庫正則函式,在sql中直接對比.

示例

select u.* from unit as u ,re_role_model as re where regfun('/update/'+u.id+'/',re.pageurl,re.bool) and re.roleid='admin'

關於大家關心的sql注入我這裡說下

1.會有過濾器過濾非法的url字元

2.如果你偽造了url 可以通過我的許可權過濾器,但是卻無法找到controller,404.例如 我的controller 接收路徑為 /usr/update/abc 你給我傳送了 /user/update/abc/d/c controller無法相應此請求.

3.regfun這個函式的引數不是從前臺獲取的,而是根據業務邏輯後臺拼裝的!

----------------------------------------------------許可權系統的思想基本介紹完畢了.--------------------------------

來個例項

新增管理員 admin_add 有全域性新增許可權 .*/save/.* bool 為1.

當然也可以具體到某個公司,某個部門,某個人.也就是資料集許可權

因為 有 bool 欄位做判斷. 可以很容易做出交叉許可權,例如上例的superuser 除了/admin/其他的都有許可權訪問.

save/delete/update/get/import/export其實代表了操作 可以根據需要新增角色的許可權.角色是繼承的,所以使用者可以再自己的許可權範圍內 自由分配給其他使用者.

當然有些也是可以系統定義的 例如

.*/user/delete/admin.* bool 為0 roleid為 * 任何角色都沒有許可權刪除超級管理員的許可權. 這些都是系統後臺定義的.

最小許可權.例如 普通使用者 abc只有訪問自己資訊的許可權

pageurl為: */user/update/abc.* (當然,這裡可以使用二次解析的萬用字元,暫不討論)

如果使用者abc向非法修改 使用者f的資訊 那麼訪問的url是*/user/update/f.* 資料庫沒有匹配的url,沒有許可權訪問

轉載於:https://my.oschina.net/baobao/blog/96643