使用動態Proxy和Java ACL進行使用者訪問控制機制實現
使用者訪問控制(Access control )機制總是圍繞粗粒度和細粒度兩個方面來討論:
粗粒度控制:可以規定訪問整個物件或物件群的某個層,而細粒度控制則總是在方法或屬性層進行控制,比如:
允許一個檔案為只讀是屬於粗粒度控制,而允許對這個檔案某行有寫操作則屬於細粒度控制。
一個好的使用者控制機制當然既允許粗粒度也允許細粒度控制,在Jive中我們看到是使用Proxy來達到這個目的,
但是我們也發現,由於需要對每個類都要進行細粒度控制,所以必然對每個類都要做一個Proxy類,這樣帶來了很多Proxy類,如ForumProxy ForumThreadProxy ForumFactoryProxy等,無形增加了系統複雜性。
使用動態Proxy可以很好的解決這個問題。再結合java.security.acl的ACL機制,我們就可以靈活地實現粗粒度和細粒度的雙重控制。
當一個使用者login後,我們就要在記憶體中為其建立相應的授權訪問機制,使用java.security.acl可以很方便的建立這樣一個安全系統。
首先任何一個物件都應該有個基本屬性:擁有者 或擁有者所屬組(Windows中每個目錄安全描述符都由4部分構成:物件的建立者、物件所屬的組、自由存取控制和系統存取控制)。
1. Java acl開始第一步是建立一個主體 Principal,其中SecurityOwner是主體的擁有者:
private static final Principal _securityOwner = new PrincipalImpl("SecurityOwner");
2. 當使用者login進來時,他帶有兩個基本資料:訪問密碼和他要訪問的物件ApplicationName。首先驗證使用者名稱和密碼,然後從資料庫中取出其許可權資料,建立Permission,這裡使用Feature繼承了Permission,在Feature中定義了有關許可權的細節資料(如讀 寫 刪)。
// 取出使用者和被訪問物件之間的許可權關係,這種許可權關係可能不只一個,也就是說,使用者
//可能對被訪問物件擁有讀 寫 刪等多個許可權,將其打包在Hasbtable中。
Hashtable features = loadFeaturesForUser(sApplicationName, sUserID);
3. 建立一個使用者物件
User user = new UserImpl(sUserID, new Hashtable() );
4. 為這個使用者建立一個活動的acl entry
addAclEntry( user, features);
其中最關鍵的是第四步addAclEntry,我們看看其如何實現的:
// 為這個使用者建立一個新的Acl entry
AclEntry newAclEntry = new AclEntryImpl( user);
//遍歷Hashtable features,將其中多種許可權加入:
....
feature = (Feature) hFeatures.get(keyName);
newAclEntry.addPermission( feature );
....
最後也要加入主體擁有者SecurityOwner
這樣一個安全體系就已經建立完成。
當你在系統中要檢驗某個使用者使用擁有某個許可權,如讀的權利時,只要
acl.checkPermission(user, feature )就可以,acl是ACL的一個例項,這樣許可權檢查就交給
java.security.acl.ACL 去處理了。
有了ACL機制後,我們就可以在我們系統中使用動態Proxy模式來對具體物件或方法進行控制,比如,我們有一個Report類,有些使用者可以讀,有些使用者可以寫(哪些使用者可以讀 哪些使用者可以寫,已經在上面ACL裡部署完成)。
從Java 1.3開始, Sun提供了Dynamic Proxy API.為了使動態Proxy能夠工作,第一你必須有一個Proxy介面,還要有一個繼承InvocationHandler的Proxy類。
在下面的例子中,我們設定有三種使用者:普通人;僱員;經理.
許可權是這樣:普通人可以讀報告;僱員和經理可以修改報告。
按通常思維,我們對於讀許可權,我們設計一個具備讀的角色類:
public interface IpersonRO {
public String getName();
public String getAddress();
public String getPhoneNumber();
}
類裡面都是讀的方法,這是一種粗粒度訪問控制,也就是說把讀寫許可權只落實到類(物件)上,這樣的話,我們還要為寫的角色再建一個類,很顯然這不是一個很好的方法,使用動態proxy+acl就可以實現很好的細粒度控制。
public class ReportProxy implements InvocationHandler
{
private Map map;
public static Object newInstance(Map map,Class[] interfaces)
{
return Proxy.newProxyInstance(map.getClass().getClassLoader(), interfaces,new ReportProxy(map));
}
public ReportProxy(Map map)
{
this.map = map;
}
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable
{
Object result;
String methodName = m.getName();
if (methodName.startsWith("get"))
{
if (!acl.checkPermission(user, "read")) return null;
String name = methodName.substring(
methodName.indexOf("get")+3);
return map.get(name);
}
else if (methodName.startsWith("set"))
{
if (!acl.checkPermission(user, "write")) return null;
String name = methodName.substring(
methodName.indexOf("set")+3);
map.put(name, args[0]);
return null;
}
else if (methodName.startsWith("is"))
{
if (!acl.checkPermission(user, "read")) return null;
String name = methodName.substring(
methodName.indexOf("is")+2);
return(map.get(name));
}
return null;
}
}
粗粒度控制:可以規定訪問整個物件或物件群的某個層,而細粒度控制則總是在方法或屬性層進行控制,比如:
允許一個檔案為只讀是屬於粗粒度控制,而允許對這個檔案某行有寫操作則屬於細粒度控制。
一個好的使用者控制機制當然既允許粗粒度也允許細粒度控制,在Jive中我們看到是使用Proxy來達到這個目的,
但是我們也發現,由於需要對每個類都要進行細粒度控制,所以必然對每個類都要做一個Proxy類,這樣帶來了很多Proxy類,如ForumProxy ForumThreadProxy ForumFactoryProxy等,無形增加了系統複雜性。
使用動態Proxy可以很好的解決這個問題。再結合java.security.acl的ACL機制,我們就可以靈活地實現粗粒度和細粒度的雙重控制。
當一個使用者login後,我們就要在記憶體中為其建立相應的授權訪問機制,使用java.security.acl可以很方便的建立這樣一個安全系統。
首先任何一個物件都應該有個基本屬性:擁有者 或擁有者所屬組(Windows中每個目錄安全描述符都由4部分構成:物件的建立者、物件所屬的組、自由存取控制和系統存取控制)。
1. Java acl開始第一步是建立一個主體 Principal,其中SecurityOwner是主體的擁有者:
private static final Principal _securityOwner = new PrincipalImpl("SecurityOwner");
2. 當使用者login進來時,他帶有兩個基本資料:訪問密碼和他要訪問的物件ApplicationName。首先驗證使用者名稱和密碼,然後從資料庫中取出其許可權資料,建立Permission,這裡使用Feature繼承了Permission,在Feature中定義了有關許可權的細節資料(如讀 寫 刪)。
// 取出使用者和被訪問物件之間的許可權關係,這種許可權關係可能不只一個,也就是說,使用者
//可能對被訪問物件擁有讀 寫 刪等多個許可權,將其打包在Hasbtable中。
Hashtable features = loadFeaturesForUser(sApplicationName, sUserID);
3. 建立一個使用者物件
User user = new UserImpl(sUserID, new Hashtable() );
4. 為這個使用者建立一個活動的acl entry
addAclEntry( user, features);
其中最關鍵的是第四步addAclEntry,我們看看其如何實現的:
// 為這個使用者建立一個新的Acl entry
AclEntry newAclEntry = new AclEntryImpl( user);
//遍歷Hashtable features,將其中多種許可權加入:
....
feature = (Feature) hFeatures.get(keyName);
newAclEntry.addPermission( feature );
....
最後也要加入主體擁有者SecurityOwner
這樣一個安全體系就已經建立完成。
當你在系統中要檢驗某個使用者使用擁有某個許可權,如讀的權利時,只要
acl.checkPermission(user, feature )就可以,acl是ACL的一個例項,這樣許可權檢查就交給
java.security.acl.ACL 去處理了。
有了ACL機制後,我們就可以在我們系統中使用動態Proxy模式來對具體物件或方法進行控制,比如,我們有一個Report類,有些使用者可以讀,有些使用者可以寫(哪些使用者可以讀 哪些使用者可以寫,已經在上面ACL裡部署完成)。
從Java 1.3開始, Sun提供了Dynamic Proxy API.為了使動態Proxy能夠工作,第一你必須有一個Proxy介面,還要有一個繼承InvocationHandler的Proxy類。
在下面的例子中,我們設定有三種使用者:普通人;僱員;經理.
許可權是這樣:普通人可以讀報告;僱員和經理可以修改報告。
按通常思維,我們對於讀許可權,我們設計一個具備讀的角色類:
public interface IpersonRO {
public String getName();
public String getAddress();
public String getPhoneNumber();
}
類裡面都是讀的方法,這是一種粗粒度訪問控制,也就是說把讀寫許可權只落實到類(物件)上,這樣的話,我們還要為寫的角色再建一個類,很顯然這不是一個很好的方法,使用動態proxy+acl就可以實現很好的細粒度控制。
public class ReportProxy implements InvocationHandler
{
private Map map;
public static Object newInstance(Map map,Class[] interfaces)
{
return Proxy.newProxyInstance(map.getClass().getClassLoader(), interfaces,new ReportProxy(map));
}
public ReportProxy(Map map)
{
this.map = map;
}
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable
{
Object result;
String methodName = m.getName();
if (methodName.startsWith("get"))
{
if (!acl.checkPermission(user, "read")) return null;
String name = methodName.substring(
methodName.indexOf("get")+3);
return map.get(name);
}
else if (methodName.startsWith("set"))
{
if (!acl.checkPermission(user, "write")) return null;
String name = methodName.substring(
methodName.indexOf("set")+3);
map.put(name, args[0]);
return null;
}
else if (methodName.startsWith("is"))
{
if (!acl.checkPermission(user, "read")) return null;
String name = methodName.substring(
methodName.indexOf("is")+2);
return(map.get(name));
}
return null;
}
}
相關文章
- Java進階 | Proxy動態代理機制詳解Java
- 演示:動態訪問控制列表(帶鎖的ACL)
- IOS - ACL (訪問控制列表)iOS
- 程式設計實現遍歷ACL訪問控制列表檢查程式訪問許可權程式設計訪問許可權
- Java動態代理和反射機制Java反射
- Redis 6.0 訪問控制列表ACL說明Redis
- 配置 Linux 的訪問控制列表(ACL)Linux
- Linux Kernel ACL訪問控制漏洞(轉)Linux
- Nginx執行控制虛擬主機和訪問控制Nginx
- 實戰Kafka ACL機制Kafka
- docker使用Open Policy Agent(OPA)進行訪問控制Docker
- Java Proxy動態代理Java
- Java使用Porxy和InvocationHandler實現動態代理Java
- 不使用反射進行C#屬性的執行時動態訪問反射C#
- SAP CDS entity 中使用 @readonly 進行訪問控制
- ora-24247 :網路訪問被訪問控制列表(ACL)拒絕
- 訪問使用者中心實現認證
- Java代理設計模式(Proxy)的四種具體實現:靜態代理和動態代理Java設計模式
- 使用Java和Spring Retry實現重試機制JavaSpring
- 大廠高階工程師面試必問系列:Java動態代理機制和實現原理詳解工程師面試Java
- 配置ACL在網路服務中訪問控制
- 使用Virtual Private Database實現細粒度訪問控制Database
- 使用DBMS_RLS實現細粒度訪問控制
- java 訪問控制符和supper,thisJava
- 控制普通使用者訪問資料字典
- HCNA Routing&Switching之訪問控制列表ACL
- Struts2實現訪問控制
- 【RAC】RAC 實現IP訪問控制
- Java 動態代理機制詳解Java
- 使用Java和Flyway進行資料庫版本控制Java資料庫
- Spring Security實現基於RBAC的許可權表示式動態訪問控制Spring
- 支援 ACL 訪問控制、引入 HOCON 全新配置檔案格式
- SQLServer控制使用者訪問許可權表SQLServer訪問許可權
- Java JDK Proxy和CGLib動態代理示例講解JavaJDKCGLib
- Java實現在訪問者模式中使用反射Java模式反射
- Oracle動態執行表不可訪問Oracle
- 動態 SQL 和快取機制SQL快取
- java的動態代理機制詳解Java