開源jsp許可權管理,實現程式碼
事情挺讓我頭痛的,記得一年前在瀋陽,我曾經有一段時間也因因這個問題而疲於奔命,為什麼說疲於奔命呢?由
於當時專案進度不允許,導致最終系統許可權模組草草了事,每個模組都是由讀許可權字串來控制使用者ACL,當用戶無
法訪問時,提示許可權不夠。這麼做對使用者是很不負責任的,既然讓使用者看到了操作的方式和介面,為什麼又告訴用
戶沒有許可權呢?我開始懷疑我們是否應該在底層就封殺使用者的訪問許可權。
現在專案開展起來了,雖然目前我已經有了對許可權控制的一套方案,並且實施成了我的可重用框架程式碼,雖然目前
的許可權也是基於眾星捧月的AOP思想,但我至今對許可權設計仍有兩個疑惑:
疑惑一:很多同行提出方案,想要在底層就擷取使用者許可權,控制使用者對方法或者類的訪問。這樣做的好處在於可以
將系統功能與業務邏輯鬆散耦合,並且實現簡單,結構清晰,三兩個advisor、filter,或者acegi就能搞定,但在
web程式中體現出了他的劣勢,當我們將使用者的訪問拒絕在業務邏輯之外的時候,我們此時是否應該丟擲異常提示用
戶?一旦提示使用者沒有相應的許可權,我認為對於使用者來說,這就不是一個perfect practice。由此得出,我們根本
就不應該讓使用者做此次操作,而控制使用者操作的源頭就是介面,也就是說,在介面上我們就應該對使用者的許可權元素(
如新增按鈕、功能選單等)進行控制。此時,一對矛盾出現了,要控制介面上形形色色的元素只有兩種辦法,一,將
許可權與你的介面結合起來設計,這將違背AOP的思想,也使得系統控制模組的重用性大大下降,二,我們借鑑
primeton的想法,將許可權控制的理念抽取出來,單獨做成一套許可權系統,解決你所有的需要許可權控制的系統需求,
這樣也有令人頭痛的問題,你的所有想用它來控制權限的系統,必須介面上統一風格。或許這樣的方式對商業web系
統是合適的,畢竟需要你大刀闊斧個性化的地方不多,但我們卻很難保證在未來幾年內商業web系統的風格不改變。
再者,開發這麼一個系統也不是一蹴而就的事,在這個問題上一直讓我困惑不已。
疑惑二:大多應用的許可權判定是基於許可權字串的,但儲存在資料庫中的許可權字串能夠判定的許可權並不多,在我
們這次專案中,我引用了基於二進位制的8421許可權判定法則,我深深的感覺到許可權字串的弱勢,這使我想起了中國
古老一套數學理論-“盈不足術”,超遞增序列的魅力在我眼前滑過,
首先我來解釋一下盈餘不足理論:有十隻盒子,第一個盒子裡放一個盤子,第二個盒子裡放兩隻,第三個盒子裡放
四隻,第四個盒子裡放八隻……第九個盒子裡放256只,第十個盒子放512只,即第N只箱子裡放2^(N-1)只盤子,一
共1023只。那麼命題如下:在1023這個數字之內,任何一個數目都可以由這十隻盒子裡的幾隻組合相加而成。那麼1
、2、4、8、16、32、64、128、256、512這個序列為什麼有這麼個魔力?這個數列的特點:1、每項是後一項的二倍
,2、每項都比前面所有項的和大,而且大1。這個1就是關鍵,就因為這個1,它才可以按1遞增,拼出總和之內任意
一個整數。這個序列叫做超遞增序列,它是解決揹包問題的基礎。3、拼出總和之內任意一個整數可以由這個序列中
的一些數構成,且構成方法唯一,據說是密碼學中的NP定理。譬如說這個數列總合中20這個數,只能由16+4一種方
法構成,由此延伸出來,如果綜合中這個資料代表一個權值,我們可以解出它的所有構成引數(操作),如20這個
資料,我們可以挨個和序列中每一項按位與,得出來如果不等於0,就說明他是由這個數構成的。
儲存權值到int還是varchar對於我們來說是個問題,當然,儲存字串的好處是運算壓力小。我們可能聽過一個故
事,就是把這個超遞增序列延伸到第64項,就是那個術士和皇帝在國際象棋棋盤上要米粒的傳說。64項的和是一個
天文數字!但計算機本身就是一個只認識二進位制的機器!很多程式設計師整天只關心架構,甚至不知道或者不關心位操
作是什麼玩意,當然我們有朋友擔心資料庫的int不夠長,那麼既然可以儲存一個只有0、1組成的varchar字串,
為什麼不能儲存一個十六進位制的字串,有人規定varchar只能儲存01嗎?十六進位制串的長度正好是二進位制的四分之
一。
由此我們可以無限制的擴充套件權值操作。
在最近的專案裡,我對許可權的控制分成兩個部分,第一就是使用者體驗上,我設定了一個許可權標籤,從資料庫中抽取
許可權資訊,然後做到標籤裡,也湊或算成是介面AOP了,第二就是底層的攔截,用了Spring 的AOP,為的是防止許可權
衝突,雙管齊下。暫時解決許可權所需,另外在演算法上我用了16進位制的許可權判別程式碼,雖然配置較麻煩,寫完程式碼還
要寫文件說明,不過也解決了許可權繁雜又多的問題,暫時就這樣了,嘿嘿,以後有空再研究。
_________________________________________________
首先上文許可權設計拙見(1)中只是想記錄下自己許可權設計上的一點看法,以及將自己日常最常用的許可權解決方案記
錄下來以供日後回顧,沒想到有朋友關注此類的設計,那就只能先把程式碼拿出來獻醜了,拋磚引玉,大家共同探討
學習
接著上文來說,上文所討論的許可權設計是一條思路,但既然是web應用,少不了資料庫的支援,本文我們來討
論一下資料庫的設計。(以下想法及思路僅僅代表本人拙見)
說到許可權的資料庫設計,必先理清許可權中幾種實體及其關係,此部分想必有過設計許可權經驗的同仁都知道怎
麼設計了,網上擺渡一下也是一褲衩子一褲衩子的,我們就在最平凡直觀的資料庫關係的基礎上來建立許可權。下面
是我的幾個表(所有的表都帶有一個pk_id,作為表的自動生成的唯一主鍵):
使用者表(T_UserInfo):
1/**//*==============================================================*/
2/**//* Table: T_UserInfo */
3/**//*==============================================================*/
4create table T_UserInfo
5(
6 pk_id NUMBER not null,
7 name VARCHAR2(20),
8 sex BOOLEAN,
9 age int,
10 emp_num NUMBER,
11 polity int,
12 unit VARCHAR2(50),
13 department VARCHAR2(20),
14 specialty int,
15 position VARCHAR2(10),
16 offtel VARCHAR2(20),
17 famtel VARCHAR2(20),
18 post_state VARCHAR2(10),
19 remark VARCHAR2(100),
20 constraint PK_T_USERINFO primary key (pk_id)
21);使用者表就不多說了,都是一些常用欄位,年齡、電話、職位等,建議大家建立一個通用一些,欄位多一些的一
個使用者表,便於以後擴充套件,以後如果有特殊需求,不用擴這個基本表,可以通過主外來鍵關係來新建一個表,用於擴
充欄位
角色表(T_RoleInfo):
1/**//*==============================================================*/
2/**//* Table: T_RoleInfo */
3/**//*==============================================================*/
4create table T_RoleInfo
5(
6 pk_id number not null,
7 role_name VARCHAR2(20),
8 role_desc VARCHAR2(100),
9 parent_role_id NUMBER,
10 constraint PK_T_ROLEINFO primary key (pk_id)
11);角色表中需要說明的就一個parent_role_id父角色id,此欄位用來擴充套件角色的繼承關係。
資源表(T_ResourceInfo):
1/**//*==============================================================*/
2/**//* Table: T_ResourceInfo */
3/**//*==============================================================*/
4create table T_ResourceInfo
5(
6 pk_id NUMBER not null,
7 module_name VARCHAR2(20),
8 module_code VARCHAR2(10),
9 module_desc VARCHAR2(100),
10 privilege_name VARCHAR2(10),
11 privilege_code CHAR,
12 privilege_desc VARCHAR2(100),
13 constraint PK_T_RESOURCEINFO primary key (pk_id)
14);
15這個表需要說明的就比較多了,首先該表用來記錄資源與資源許可權,我這邊所謂的資源就是實體,就是資料庫表
,角色需要對應到資源,有些角色對該資源有許可權,有些角色則對該資源無許可權,角色可對此資源操作的許可權也不
同。說白了,就是不同的角色對不同的資料庫表的操作許可權不同。因此我們這裡的資源就是資料庫表。
module_name:資源名;module_code:資原始碼(存放資料庫表名);
privilege_name:許可權名;privilege_code:許可權程式碼(代表權限的code,也就是我們上文所說的權值)
例如角色a對資料庫表T_UserInfo有新增與刪除的許可權則該表應該按照如下配置:
module_name:人員資訊;
module_code:T_UserInfo
privilege_name:新增與刪除
privilege_code:6
這裡我們假設的是2的0次方為新增許可權,2的1次方為新增許可權,2的2次方為刪除許可權,2的3次方為更新許可權,則擁
有新增與刪除許可權就應該為2的1次方+2的2次方=6,其實2的幾次方代表什麼含義我們可以另外開個資料庫表來配置
(或者xml檔案)此處我們忽略這些步驟。當然如果你的許可權較多,譬如你還希望a這個角色對人員資訊表有上傳得
許可權,我們可以將將上傳許可權定義為2的4次方,16,16的16進位制數為10,記錄在資料庫裡的形式應該為0x10如果a角
色擁有新增、刪除、更新、上傳許可權,則a的權值應該為2的1次方+2的2次方+2的3次方+2的4次方=30,用16進位制來表
示就應該為0x1E,記錄16進位制資料,你不用擔心位數不夠。
剩餘的就是幾張關係表了:
人員角色關係表(T_R_User_Role):
1/**//*==============================================================*/
2/**//* Table: T_R_user_role */
3/**//*==============================================================*/
4create table T_R_user_role
5(
6 pk_id NUMBER not null,
7 user_id NUMBER,
8 role_id NUMBER,
9 constraint PK_T_R_USER_ROLE primary key (pk_id)
10);
11角色資源關係表(T_R_Role_Resource)
1/**//*==============================================================*/
2/**//* Table: T_R_role_resource */
3/**//*==============================================================*/
4create table T_R_role_resource
5(
6 pk_id NUMBER not null,
7 role_id NUMBER,
8 res_id NUMBER,
9 constraint PK_T_R_ROLE_RESOURCE primary key (pk_id)
10);
11當然如果你不怕麻煩,可以新增進去組(group)、系統(system)、組織(organization),建立起一套屬於你自己的
完整的許可權解決方案,作為系統無關的模組去套用到每個你所架構的應用中去,那是一件極爽的事情。
連續劇開始了,暫時擱筆~~
__________________________________________________________________________
在上文中我們提到了一個資源對應一個數據庫表,在T_ResourceInfo表中我們也提到了有一個欄位專門來記錄表名
,然後我書寫一個資源配置檔案,用來配置我的業務類與資源的對應關係,程式碼如下:
1<?xml version="1.0" encoding="GB2312"?>
2<data>
3 <mapping SysName="s">
4 <module BusinessClass="com.ideal.framework.business.businessface.IBLogin"
TableName="user_info"/>
5 </mapping>
6</data>其中BusinessClass代表業務介面,TableName代表該業務介面所要操作的資料實體(資料表),此處的
TableName必須與T_ResourceInfo中的Module_Code一致。
使用者登入後,需要操作T_UserInfo這個表時,我們的邏輯將會把請求帶入IBLogin這個業務邏輯中,在我們的AOP模
塊中,可以用MethodInterceptor來截獲當前使用者想要操作的業務邏輯,當AOP模組截獲了使用者的請求,並判斷使用者
想要操作IBLogin這個業務邏輯,它將在上述的mapping檔案中去找該業務邏輯對應的資源user_info,然後去資源表
中判斷該使用者是否有操作user_info的許可權。
(注:上述xml檔案在系統初始化時候載入入記憶體中,我們也可以將許可權資訊也載入在記憶體中,不會很大,一切資源
在記憶體中操作,非常快)
下面我貼點程式碼,在系統初始化時:
1package com.ideal.framework;
2
3import java.util.*;
4import java.sql.*;
5import com.ideal.framework.dao.daoface.*;
6import com.ideal.framework.po.*;
7
8public class ResourceContainer
9{
10 public static boolean change_resource; //更新資源 系統持久
11 public static Vector resource_container = new Vector(); //資源容器 使用者持久
12 private IUserRoleDAO m_user_role_dao;
13 private IRoleResourceDAO m_role_resource_dao;
14 private IUserDAO m_user_dao;
15
16 public ResourceContainer()
17{
18 }
19
20 public void setUserResource()
21 {
22 System.out.println("initialize resource:");
23 List user_list = m_user_dao.getAllUser();
24 for (int i = 0; i < user_list.size(); i++)
25 {
26 UserInfo user = (UserInfo) user_list.get(i);
27 List role_list = m_user_role_dao.getRoleInfo(user);
28 for (int j = 0; j < role_list.size(); j++)
29 {
30 RoleInfo role = (RoleInfo) role_list.get(j);
31 List resource_list = m_role_resource_dao.
32 getResourceInfo(role);
33 for (int k = 0; k < resource_list.size(); k++)
34 {
35 Hashtable hash = new Hashtable();
36 hash.put(user.getLoginId(), resource_list.get(k));
37 hash.put("Unit_"+user.getLoginId(), user.getUnit());
38 hash.put("Role_"+user.getLoginId(), role.getRoleName());
39 ResourceContainer.resource_container.add(hash);
40 }
41 }
42 }
43 }
44
45 public Vector getResource_container()
46 {
47 return resource_container;
48 }
49
50 public void setResource_container(Vector resource_container)
51 {
52 this.resource_container = resource_container;
53 }
54
55 public IRoleResourceDAO getM_role_resource_dao()
56 {
57 return m_role_resource_dao;
58 }
59
60 public IUserDAO getM_user_dao()
61 {
62 return m_user_dao;
63 }
64
65 public IUserRoleDAO getM_user_role_dao()
66 {
67 return m_user_role_dao;
68 }
69
70 public void setM_role_resource_dao(IRoleResourceDAO m_role_resource_dao)
71 {
72 this.m_role_resource_dao = m_role_resource_dao;
73 }
74
75 public void setM_user_dao(IUserDAO m_user_dao)
76 {
77 this.m_user_dao = m_user_dao;
78 }
79
80 public void setM_user_role_dao(IUserRoleDAO m_user_role_dao)
81 {
82 this.m_user_role_dao = m_user_role_dao;
83 }
84
85 public void setChange_resource(boolean change_resource)
86 {
87 this.change_resource = change_resource;
88 }
89
90 public boolean isChange_resource()
91 {
92 return change_resource;
93 }
94}
95將使用者對應的角色,資源資訊載入如記憶體,另外在初始化時候的xml檔案的樹形結構也載入入記憶體,這邊就不貼代
碼了
下面是AOP模組的advice程式碼:
package com.ideal.framework.sys.advice;
/** *//**
* <p>Title: BusinessAccessAdvisor</p>
* <p>Description: 業務模組AOP許可權監聽器</p>
* <p>Copyright: Copyright (c) 2006</p>
* <p>Company: ideal</p>
* @author alex
* @version 1.0
*/
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import com.ideal.framework.InitResource;
import com.ideal.framework.util.XMLUtil;
import java.util.ArrayList;
import java.util.Hashtable;
import com.ideal.framework.sys.accesscontrol.GenericAccessBase;
import java.lang.reflect.Field;
import com.ideal.framework.po.*;
import java.lang.reflect.Method;
import java.util.*;
import java.io.*;
import javax.servlet.http.HttpServletRequest;
public class BusinessAccessAdvisor
implements MethodInterceptor
{
public BusinessAccessAdvisor()
{
}
public Object invoke(MethodInvocation invocation) throws
Throwable
{
String user_name = "";
Object obj = invocation.getArguments()[1];
if (obj instanceof HttpServletRequest)
{
HttpServletRequest request = (HttpServletRequest)obj;
user_name = (String)request.getSession().getAttribute("UserName");//取出使用者名稱
}
String bean_name = invocation.getMethod().getDeclaringClass().getName();//取出使用者想要操作的
業務邏輯
XMLUtil xml = (XMLUtil) InitResource.context.getBean("XMLUtil");
ArrayList list = xml.getFieldList("mapping", "s", xml.doc);
for (int i = 0; i < list.size(); i++)
{
Hashtable hash = (Hashtable) list.get(i);
if (hash.get("BusinessClass").equals(invocation.getMethod().//判斷使用者是否有權操作該業務
邏輯所對應表
getDeclaringClass().getName()))
{
String table_name = (String) hash.get("TableName");
GenericAccessBase access_controller = (GenericAccessBase)
InitResource.context.getBean("GenericAccessBase");
if (access_controller.CheckAccessPrivilege(user_name, table_name))//若使用者有權操作該
表,則讓程式進入業務邏輯
{
return invocation.proceed();
}
}
}
System.out.println("no permission .reject by " + bean_name);
return null;
}
}
下面是判斷使用者是否具有操作該表許可權的類:
1package com.ideal.framework.sys.accesscontrol;
2
3import com.ideal.framework.InitResource;
4import com.ideal.framework.util.XMLUtil;
5import com.ideal.framework.po.UserInfo;
6import com.ideal.framework.ResourceContainer;
7import java.util.*;
8//import com.ideal.framework.po.ResourceInfo;
9
10public class GenericAccessBase
11{
12 UserInfo user;
13
14 public GenericAccessBase()
15 {
16 }
17
18 public void setUser(UserInfo user)
19 {
20 this.user = user;
21 }
22
23 public boolean CheckAccessPrivilege(String user_name, String table_name)
24 {
25 for (int i = 0; i < ResourceContainer.resource_container.size(); i++)
26 {
27 Hashtable temp_hash = (Hashtable)ResourceContainer.resource_container.get(i);//從記憶體中
取出使用者資源資訊
28 if (temp_hash.containsKey(user_name))
29 {
30 ResourceInfo resource = (ResourceInfo)temp_hash.get(user_name);
31 if (table_name.trim().toLowerCase().equals(resource.getModuleCode().trim
().toLowerCase()))//比對使用者擁有的資源和當前的table_name
32 {
33 return true;
34 }
35 }
36 }
37 return false;
38 }
39}
40ok,到此為止,我們的底層攔截就完成了,接下來就是介面許可權處理,介面許可權比較複雜,因為使用者可能具有添
加許可權,沒有上傳許可權,有下載許可權卻沒有更新許可權等,情況很複雜,所以我們這邊必須有一個判斷當前使用者是否
具有這些複雜許可權的類:
1package com.ideal.framework.sys.privilege;
2
3/** *//**
4 * <p>Title: GenericPrivilegeBase</p>
5 * <p>Description: 通用許可權法則</p>
6 * <p>Copyright: Copyright (c) 2006</p>
7 * <p>Company: ideal</p>
8 * @author alex
9 * @version 1.0
10 */
11
12public class GenericPrivilegeBase
13{
14 public final static int NO_PRIVILEGE = 0;
15 public final static int QUERY_OR_USE_PRIVILEGE = 1;//察看許可權
16 public final static int CREATE_PRIVILEGE = 2;//新增許可權
17 public final static int DELETE_PRIVILEGE = 4;//刪除許可權
18 public final static int UPDATE_PRIVILEGE = 8;//更新許可權
19 public final static int ALL_PRIVILEGE = QUERY_OR_USE_PRIVILEGE |
20 CREATE_PRIVILEGE | DELETE_PRIVILEGE | UPDATE_PRIVILEGE;//增刪改查許可權
21
22 public GenericPrivilegeBase()
23 {
24 }
25
26 public static boolean isValidPrivilege(int privilege)//判斷是否具有許可權
27 {
28 if ( (privilege & QUERY_OR_USE_PRIVILEGE) != 0)
29 {
30 return true;
31 }
32
33 if ( (privilege & CREATE_PRIVILEGE) != 0)
34 {
35 return true;
36 }
37
38 if ( (privilege & DELETE_PRIVILEGE) != 0)
39 {
40 return true;
41 }
42
43 if ( (privilege & UPDATE_PRIVILEGE) != 0)
44 {
45 return true;
46 }
47
48 return false;
49 }
50
51 public static boolean checkQueryPrivilege(int privilege)//判斷是否具有察看許可權
52 {
53 if ( (privilege & QUERY_OR_USE_PRIVILEGE) != 0)
54 {
55 return true;
56 }
57 else
58 {
59 return false;
60 }
61 }
62
63 public static boolean checkUsePrivilege(int privilege)
64 {
65 if ( (privilege & QUERY_OR_USE_PRIVILEGE) != 0)
66 {
67 return true;
68 }
69 else
70 {
71 return false;
72 }
73 }
74
75 public static boolean checkCreatePrivilege(int privilege)//判斷是否有新增許可權
76 {
77 if ( (privilege & CREATE_PRIVILEGE) != 0)
78 {
79 return true;
80 }
81 else
82 {
83 return false;
84 }
85 }
86
87 public static boolean checkDeletePrivilege(int privilege)//判斷是否有刪除許可權
88 {
89 if ( (privilege & DELETE_PRIVILEGE) != 0)
90 {
91 return true;
92 }
93 else
94 {
95 return false;
96 }
97 }
98
99 public static boolean checkUpdatePrivilege(int privilege)
100 {
101 if ( (privilege & UPDATE_PRIVILEGE) != 0)
102 {
103 return true;
104 }
105 else
106 {
107 return false;
108 }
109 }
110}
111然後我們自定義兩個標籤,Privilege與noPrivilege用來判斷使用者是否具有許可權,這兩個標籤必須具有三個基本
的attribute,beanName:當前所要操作的哪個資源;scope:使用者資訊存放在哪個域;operation:使用者想要進行什
麼操作
貼一個privilege標籤的程式碼:
1package com.ideal.framework.tag;
2
3import javax.servlet.jsp.tagext.BodyTagSupport;
4import javax.servlet.jsp.tagext.*;
5import javax.servlet.http.*;
6import javax.servlet.jsp.*;
7import java.sql.*;
8import java.io.*;
9import com.ideal.framework.*;
10import com.ideal.framework.po.ResourceInfo;
11import java.util.Hashtable;
12import com.ideal.framework.sys.privilege.GenericPrivilegeBase;
13
14public class PrivilegeTag
15 extends BodyTagSupport
16{
17 String operation;
18 private String beanName;
19 private String scope;
20
21 public PrivilegeTag()
22 {
23 super();
24 }
25
26 public void setOperation(String operation)
27 {
28 this.operation = operation;
29 }
30
31 public void setBeanName(String beanName)
32 {
33 this.beanName = beanName;
34 }
35
36 public void setScope(String scope)
37 {
38 this.scope = scope;
39 }
40
41 public int doStartTag() throws JspTagException
42 {
43 if (scope == null || scope.equals(""))
44 return SKIP_BODY;
45 else
46 {
47 String user_name = "";
48 if (scope.equalsIgnoreCase("session"))
49 {
50 HttpSession session = pageContext.getSession();
51 user_name = (String) session.getAttribute("UserName");
52 }
53 else
54 {
55 HttpServletRequest request = (HttpServletRequest) pageContext.
56 getRequest();
57 user_name = (String) request.getAttribute("UserName");
58 }
59
60 for (int i = 0; i < ResourceContainer.resource_container.size(); i++)
61 {
62 Hashtable temp_hash = (Hashtable) ResourceContainer.
63 resource_container.get(i);
64 if (temp_hash.containsKey(user_name))
65 {
66 ResourceInfo resource = (ResourceInfo) temp_hash.get(
67 user_name);
68 if (beanName.trim().toLowerCase().equals(resource.
69 getModuleCode().trim().toLowerCase()))
70 {
71 if(this.checkPrivilege(resource.getPrivilegeCode()) == EVAL_BODY_TAG)
72 return EVAL_BODY_TAG;
73 }
74 }
75 }
76
77 }
78 return SKIP_BODY;
79return EVAL_BODY_TAG;
80 }
81
82 public int checkPrivilege(String privilege)
83 {
84 int int_privilege = 0;
85 try
86 {
87 int_privilege = Integer.parseInt(privilege);
88 }
89 catch (NumberFormatException ex)
90 {
91 System.out.println(ex.getMessage());
92 }
93 GenericPrivilegeBase gpb = new GenericPrivilegeBase();
94 if (operation.equals("NONE"))
95 return EVAL_BODY_TAG;
96 if (operation.equals("QUERY"))
97 if (gpb.checkQueryPrivilege(int_privilege))
98 return EVAL_BODY_TAG;
99 if (operation.equals("CREATE"))
100 if (gpb.checkCreatePrivilege(int_privilege))
101 return EVAL_BODY_TAG;
102 if (operation.equals("DELETE"))
103 if (gpb.checkDeletePrivilege(int_privilege))
104 return EVAL_BODY_TAG;
105 if (operation.equals("UPDATE"))
106 if (gpb.checkUpdatePrivilege(int_privilege))
107 return EVAL_BODY_TAG;
108 if (operation.equals("USE"))
109 if (gpb.checkUsePrivilege(int_privilege))
110 return EVAL_BODY_TAG;
111 return SKIP_BODY;
112 }
113
114 public int doAfterBody() throws JspTagException
115 {
116 return SKIP_BODY;
117 }
118
119 public int doEndTag() throws JspTagException
120 {
121 try
122 {
123 if (bodyContent != null)
124 {
125 bodyContent.writeOut(bodyContent.getEnclosingWriter());
126 }
127 }
128 catch (IOException ex)
129 {
130 throw new JspTagException("IO Error:" + ex.getMessage());
131 }
132 return EVAL_PAGE;
133 }
134
135 public void doInitBody() throws JspTagException
136 {
137 }
138
139 public void setBodyContent(BodyContent bodyContent)
140 {
141 this.bodyContent = bodyContent;
142 }
143}
144在頁面上,我們如此使用該標籤:
1<privilege beanName="user_info" scope="session" operation="create">
2 <input type="button" value="新增">
3</privilege>
如此,系統會自動根據當前session中的使用者來判斷是否需要顯示當前的新增按鈕。
到此所有許可權的程式碼完成,在此套許可權設計中,我始終抱著AOP的想法:讓他屬於一個系統切面,以後再開發其他系
統時,作為一個模組就可以載入上去,與系統無關
相關推薦
開源jsp許可權管理,實現程式碼
事情挺讓我頭痛的,記得一年前在瀋陽,我曾經有一段時間也因因這個問題而疲於奔命,為什麼說疲於奔命呢?由 於當時專案進度不允許,導致最終系統許可權模組草草了事,每個模組都是由讀許可權字串來控制使用者ACL,當用戶無 法訪問時,提示許可權不夠。這麼做對使用者是很不負責任的,既然讓使用者看到了操作的方式和介面,為什
Shiro 整合SpringMVC 並且實現許可權管理,登入和登出
Apache Shiro是Java的一個安全框架。目前,使用Apache Shiro的人越來越多,因為它相當簡單,對比Spring Security,可能沒有Spring Security做的功能強大,但是在實際工作時可能並不需要那麼複雜的東西,所以使用小而簡單
Jenkins+maven+git 實現自動構建、許可權管理、靜態程式碼檢測、遠端部署、傳送郵件功能
Jenkins配置 1. 使用者許可權設定 配置->Configure Global Security (注:想讓匿名使用者可以瀏覽jenkins網站 需勾選Overall 中的read 和 Job
Django實戰1-許可權管理功能實現-01:搭建開發環境
1 專案開發環境 語言環境: python3.6.2 , django-2.1.2 資料庫環境:sqlite3(開發環境使用,部署環境使用mysql5.6) 開發工具:pycharm 2 安裝python 說明:已經安裝過python3.6環境的可以跳過此步。python安裝包下載地址
利用svn鉤子hooks/post-commit,實現程式碼更新,自動執行指令碼
1. 在svn伺服器對應的專案中會存在以下幾個目錄和檔案 conf db format hooks locks README.txt 其中目錄hooks是放置程式碼提交執行的檔案 進入 hooks目錄新建一個 post-comm
許可權管理,資料備份、pymysql模組
許可權管理 許可權管理重點 MySQL 預設有個root使用者,但是這個使用者許可權太大,一般只在管理資料庫時候才用。如果在專案中要連線 MySQL 資料庫,則建議新建一個許可權較小的使用者來連線。 在 MySQL 命令列模式下輸入如下命令可以為 MySQL 建立一個新使用者:
功能許可權和資料許可權管理的實現
1 引言 許可權,可分為“功能(操作)許可權”和資料許可權兩種,在系統中,兩種許可權應當同時有效。例如,在windows系
RBAC許可權管理系統實現思路(一)
RBAC(Role-Based Access Contro) 是基於角色的許可權訪問控制,系統根據登入使用者的角色不同,從而給予不同的系統訪問許可權,角色的許可權隨角色創立時進行分配。 首先,許可權控制很多系統中都需要,但是不同的系統對於許可權的敏感程度不同,
一個完整的簡單jsp+servlet例項,實現簡單的登入
開發環境myeclipse+tomcat8 1、先建立web project,專案名為RegisterSystem, 2、在WebRoot 目錄下建立login.jsp檔案: <%@
許可權管理系統實現思路(SpringCloud+Thymeleaf)(二)
許可權分配 下面主要來說說Thymeleaf模板使用和許可權分配的實現思路。 先看效果圖: 實現該功能的思路是:傳往前端的資料為Map,該Map以columnName(許可權分欄名)為key,以該分欄下的所有許可權為value。因為要回顯許
Unity程式設計技巧:使用巨集定義,讓程式碼更整潔,實現程式碼和渠道SDK解耦等
筆者從一年前開始做VR開發,移動端PC端的應用都有,因為當前VR市場還很混亂,並且硬體標準太多單我使用過作開發的VR裝置就有5、6種之多,更別說只是用過聽過的裝置,並且每一家的API都不一樣,這也增加了發不同的渠道包的工作量。這裡我將就我使用的只用解決方案
許可權管理(資料庫程式碼編寫)
--許可權表(選單表) create table Premisson_Func ( Id int primary key identity(1,1), Name nvarchar(128), ---選單名 url nvarchar(216), ---
android6.0動態許可權管理,小米bug適配
在Android6.0以後開始,對於部分敏感的“危險”許可權,需要在應用執行時向用戶申請,只有使用者允許的情況下這個許可權才會被授予給應用。這對於使用者來說,無疑是一個提升安全性的做法。那麼對於開發者,應該怎麼做呢? Android6.0規定的危險許可權有下面
【無私分享:從入門到精通ASP.NET MVC】從0開始,一起搭框架、做專案(8) 許可權管理,自定義許可權,擴充套件許可權
索引 簡述 今天我們來做許可權的管理,這篇比較多 希望新手朋友慢慢消化 專案準備 我們用的工具是:VS 2013 + SqlServer 2012 + IIS7.5 希望大家對ASP.NET MVC有一個初步的理解,理論性的東西我們不做過多解釋,有些地方不理解也沒關係,會用就行了,用的多了,用的
PHPStorm 配置遠端伺服器資料夾在本地windows映象,實現程式碼自動同步(類似於Samba架構檔案同步功能)
場景介紹:這是一種類似samba架構,也和 filezilla+xshell 模式相類似的程式碼檔案同步的模式,但是卻更加優雅,也更加方便簡潔。環境介紹:本地windows端:編輯器phpstorm遠端Linux端:centos(香港節點伺服器)LNMP一、實現檔案同步1、在
SSM環境shiro跨域AJAX許可權管理,資料請求
首先,專案環境是用: Java後端:Myeclipse10 後端採用框架:ssm,沒有用到mevan管理jar包 實行前後分離開發模式,通過api介面向前端傳遞資料 web前端:HTML5 首先跨域問題,重寫過濾器Filter的doFilter()方法 @Overri
關於Android 6.x 及以上許可權管理,閃退
原因1. 沒有授權檢查; 原因2. 許可權檢查與宣告不匹配 例如: 近期,維護一個接手的App,由於歷史原因,沒有許可權管理,直接導致在高版本的Android上閃退。 直接匯入了以前專案使用的以下程式碼 public static String[] check
SAP許可權管理,我的理解
本人2001年至今一直從事basis工作,曾經是erphome-basis版主之一,管理過多個500人以上的sap系統N年,創有BASIS終極授權の內部顧問引數檔案的產生 https://github.com/basis100/SAPauthor我經歷的多個ERP系統中,
SVN版本管理,提交程式碼規範
專案開發要求: 1、工作目錄要及時更新,不要和SVN伺服器有太大的差別 2、提交程式碼時,如果出現衝突,必須仔細分析解決,不可以強行提交 3、提交程式碼之前先在本地進行測試,確保專案能編譯通過,且能夠正常執行,不可盲目提交 4、必須保證SVN上的版本是正確的,專案有錯誤時,不要進行提交 SVN注意事項,請
CAS4.0+禪道開源版11.2,實現禪道的單點登入
本文在 夜風飄塵的部落格 基礎上進行修改。所以cas的客戶端和服務端就不做詳解了,