一、權限計算相關分析
1.如何存儲權限
首先說一下權限保存的問題,一個系統中最多有多少權限呢?一個大的系統中可能有成百上千個權限需要管理。怎么保存這么多的權限?首先,我們使用一個數字中的一位保存一種權限,那么如果現在有3600種權限需要保存,我們就需要一個3600位的數字來保存該權限,首先我們如果不考慮大數的話其它數據類型是沒有辦法保存這么長的數字的。所以我們為了能夠保存這么多的權限,就引入了一個“權限組”的概念,這個權限組只是一個標識權限的容器,我們使用long類型的數字來保存63個權限,假設我們使用long類型的數字來保存權限組,那么很輕松的就能保存住幾乎近天文數字個權限。
2.如何保存權限:使用<
如果有一個添加新權限的界面,該怎么添加權限呢?首先,可以給出權限名稱和權限指向的url地址以及權限描述,但是不能提供權限位和權限碼的編輯,權限位和權限碼的計算需要系統自動計算出來。
保存權限的流程圖如下:
3.如何判斷用戶是否有指定的權限:使用&運算判斷權限
我們給給權限一個“public”的屬性,我們使用該屬性標識該資源是否需要有相關權限才能夠訪問,如果該屬性為true,表示該資源是公共資源,不需要任何權限就能訪問。每一個權限都唯一的標志了一個url,所謂的是否有權限實際上就是是否有權限訪問該url。
4.如何計算用戶的權限總和(rightSum數組)
使用|運算,公式:rightSum[right.pos]=right.pos|rightSum[right.pos];
二、權限實體相關分析
1.為了更加靈活的權限控制,引入角色的概念
角色直接和用戶實體掛鉤,用戶實體不再直接和權限實體關聯,而是通過角色實體和權限關聯。
一個用戶可以有多個角色,一個角色能夠屬于多個用戶;一個角色能夠有多個權限,一個權限能夠屬于多個角色,所以用戶和角色之間是多對多的關系,角色和權限之間也是多對多的關系。ER圖如下圖所示:
2.權限實體分析
在權限管理模塊,權限實體是不可再分割的最小實體。
(1)首先權限實體需要有一個權限名rightName,名字只是為了方便理解權限的作用;
(2)url,該url實際上是ActionName,如果帶有get類型的參數必須將參數拿掉,比如LoginAction_login.action?username=zhangsan&password=lisi,將其處理之后就變成了LoginAction_login.action
(3)權限碼rightCodes,一個表中rightCodes并不是唯一的,它只在對應的權限組中唯一,它使用long類型的數據類型進行保存,形式如1,2,4,8,16,....261
為了避免臨界值的麻煩,權限碼最大為261
(4)權限位,rightPos,也叫做權限組,這里使用一個整數保存即可,用于標識權限位所在的組,雖然只是起到標識作用,但是實際上卻是權限碼的容器。
(5)是否是公共資源標識common
(6)權限描述,沒什么說的,加上即可。
public class Right implements Serializable{
private static final long serialVersionUID = 7690933329658416384L;
private Integer rightId; //權限唯一標識id
private String rightName="未命名"; //權限名稱
private String rightUrl; //將要過濾的URL
private String rightDesc="默認描述"; //權限描述
private Long rightCodes; //權限碼
private int rightPos; //權限位,實際上就是權限組的類別
private Boolean common=true; //標識是否為公共資源的標識字段
......
}
權限實體和角色實體之間是多對多的關系,需不需要在權限映射文件中建立關聯關系?我們從不會根據權限獲取該權限屬于哪種角色,所以不要建立權限到角色的關聯關系,無用的關聯只會給系統帶來隱藏的負擔。
3.角色實體分析
角色實體需要建立到權限實體的多對多關聯關系,但是不應該建立到User實體的關聯關系,原因同上。另外增加一個roleValue,使用該值標識是否有超級管理員權限。如果該標識為“-1”,那么將會覆蓋其余的所有權限,稱為最高權限,可以訪問一切資源。
1 public class Role implements Serializable{
2 private static final long serialVersionUID = -1585936238538771703L;
3 private Integer roleId; //Role對象標識id
4 private String roleName="未命名角色"; //Role對象名稱
5 private String roleValue="0"; //Role對象值,只是在判定是超級管理員的時候有用
6 private String roleDesc="默認角色描述"; //Role對象描述
7 //建立Role到Right之間的單向多多對關系
8 private Setrights=new HashSet();//這里必須初始化一下,否則在重用保存/修改頁的時候會報錯
9 ......
10 }
4.用戶實體
只需要增加一個Set集合并建立到角色實體的多對多關系映射即可。
三、增加權限
流程:導航欄上單擊“權限管理”超鏈接跳轉到權限管理界面->在權限管理界面上單擊“增加權限”超鏈接->跳轉到增加權限頁面上->填寫表單成功之后,單擊提交,交給RightAction_saveOrUpdateRightPage.action處理,期間調用Service方法保存權限->返回權限管理界面。
當然,最核心的還是Service中的方法:
1 //添加新權限的過程
2 public void saveOrUpateRight(Right right){
3 Integer rightPos;
4 Long rightCodes;
5 //首先是針對新創建的情況
6 if(right.getRightId()==null){
7 //第一步查找最大權限位和最大權限碼
8 String hql="select max(r.rightPos),max(r.rightCodes) from Right r where r.rightPos=(select max(rr.rightPos) from Right rr)";
9 Object[] arr=(Object[]) this.rightDao.findUniqueResult(hql);
10 Integer topRightPos=(Integer) arr[0];
11 Long topRightCodes=(Long) arr[1];
12 if(topRightPos==null){
13 rightPos=0;
14 rightCodes=1L;
15 }else{
16 if(topRightCodes>=(1L<<60)){
17 rightPos=topRightPos+1;
18 rightCodes=1L;
19 }else{
20 rightPos=topRightPos;
21 rightCodes=topRightCodes<<1;
22 }
23 }
24 right.setRightPos(rightPos);
25 right.setRightCodes(rightCodes);
26 }
27 this.rightDao.saveOrUpdateEntity(right);
28 }
四、顯示所有權限,略。