14.1 Acegi眼中的領域對象
14.1 Acegi眼中的領域對象
大部分開發者都應該熟悉基于Windows NT內核的Windows操作系統,比如Windows 2000、2003、XP。事實上,Windows操作系統本身充當了管理千萬個領域對象的角色,這里的領域對象就是那些文件夾和文件。各個文件夾可以含有子文件夾,也可以含有大量的文件。文件是葉節點,它不再包含任何子元素。從領域對象的角度出發,文件夾和文件自身都持有各自的訪問控制列表(Access Control List,ACL),ACL用于給定操控這些領域對象的權限信息,比如marissa用戶可以操作shared目錄,而scott用戶不能夠操作shared目錄等。
為了同基于角色授權區分開,對于領域對象而言,訪問控制列表(Access Control List,ACL)成為了各個領域對象的“專有名詞”。這意味著,角色授權適用于Web資源和業務方法,而ACL授權適用于領域對象。各個ACL可能持有若干個ACE,即Access Control Entry(訪問控制項)。總之,各個領域對象都會存在對應它的ACL,而各個ACL會持有若干個ACE,ACE真正給出了操控當前領域對象的具體權限信息。
關于org.acegisecurity.acl與org.acegisecurity.acls包 |
早期的Acegi就提供了較好的領域對象支持,即org.acegisecurity.acl包。隨著企業用戶的日益使用,他們逐漸認識到org.acegisecurity.acl的不足之處,比如他們不能夠將特定數據庫提供的一些高級特性應用到自身的應用中、acl包操作數據庫的效率較低、對內存的使用不是非常合理等。后來,Acegi開發團隊便也在逐漸改進現有的不足之處。 自從Acegi 1.0.3開始,基于新基代碼的org.acegisecurity.acls包取代了org.acegisecurity.acl的地位,也就是說新開發的企業應用最好使用org.acegisecurity.acls提供的領域對象支持。本書僅僅專注org.acegisecurity.acls的使用,這兩個包的使用存在的差別很大。可以看出,acls包不僅克服了原有acl包的一切缺陷,而且Acegi開發團隊一直在改進acls包。Acegi開發團隊可能會在某個特定時刻將org.acegisecurity.acl包丟棄掉。 |
14.1.1 保護領域對象概述
Acegi于org.acegisecurity.acls.domain包內置了表示ACL的如下Acl接口。通過這一接口,我們能夠獲得ACL持有的ACE集合、當前ACL對應的領域對象、這一ACL的持有人(主人)、當前ACL的父ACL等。
public interface Acl extends Serializable {
//獲得當前ACL持有的ACE集合
public AccessControlEntry[] getEntries();
//當前ACL對應的領域對象
public ObjectIdentity getObjectIdentity();
//持有這一ACL的主人
public Sid getOwner();
//獲得當前ACL的父ACL
public Acl getParentAcl();
//父ACL是否允許被當前ACL繼承
public boolean isEntriesInheriting();
//用于ACL授權決定
public boolean isGranted(Permission[] permission, Sid[] sids,
boolean administrativeMode)
throws NotFoundException, UnloadedSidException;
//判斷當前ACL是否已持有傳入的sids
public boolean isSidLoaded(Sid[] sids);
}
圖14-1展示了Acegi內置的Acl繼承鏈,處于繼承鏈中的各個接口及類各有各的用途。比如,借助于MutableAcl能夠修改當前的AclImpl實例,借助于AuditableAcl能夠完成ACL中ACE的審計,借助于OwnershipAcl能夠修改當前AclImpl實例的主人。
圖14-1 Acl繼承鏈
下面給出了Acegi內置的用于表示ACE的AccessControlEntry策略接口。通常,Acl同AccessControlEntry具有1:N的關系,單個Acl持有若干個AccessControlEntry。
public interface AccessControlEntry {
//獲得其所在的ACL
public Acl getAcl();
//標識當前的ACE
public Serializable getId();
//表示的ACL(ACE)權限信息
public Permission getPermission();
//當前ACL(ACE)權限信息的持有人,比如marissa用戶
public Sid getSid();
//當前ACL(ACE)權限信息是否已經授給了Sid
public boolean isGranting();
}
圖14-2展示了Acegi內置的AccessControlEntry繼承鏈。
圖14-2 AccessControlEntry繼承鏈
在借助Acegi保護領域對象期間,開發者幾乎不用同Acl和AccessControlEntry打交道,至少不用同AclImpl和AccessControlEntryImpl實現類交互。Acl和AccessControlEntry都使用到Sid接口,而Acl還使用到ObjectIdentity接口。Sid用于表示ACL授權過程中的授權對象,比如marissa用戶、ROLE_USER角色都可以成為Sid的表示對象。圖14-3展示了Acegi內置的Sid繼承鏈。開發者將用戶名、Authentication對象傳入PrincipalSid構建器便能夠構建出PrincipalSid對象;同理,將角色、GrantedAuthority對象傳入GrantedAuthoritySid構建器便能夠構建出GrantedAuthoritySid對象。ObjectIdentity用于標識單個領域對象,這一對象的存在使得目標企業應用同Acegi間的耦合得到降低,ObjectIdentityImpl是Acegi內置的唯一ObjectIdentity實現類。
圖14-3 Sid繼承鏈
Acegi提供的ACL子系統正是圍繞Acl、AccessControlEntry、Sid、ObjectIdentity展開的,這些對象存活于業務系統與RDBMS間。也正是這些接口的存在,我們才能夠將Acegi提供的ACL子系統作用到任何RDBMS中。也就是說,Acegi提供的領域對象支持適合于所有的RDBMS、O/R Mapping技術。為了能夠從RDBMS裝載到相關對象,我們需要使用Acegi內置的如下AclService接口。
//獲得ACL
public interface AclService {
//查找到parentIdentity的所有子ObjectIdentity,ACL管理工具經常要使用到它
public ObjectIdentity[] findChildren(ObjectIdentity parentIdentity);
//通過ObjectIdentity獲得單個Acl對象
public Acl readAclById(ObjectIdentity object) throws NotFoundException;
//通過ObjectIdentity獲得僅適合于sids的單個Acl對象
public Acl readAclById(ObjectIdentity object, Sid[] sids)
throws NotFoundException;
//獲得ObjectIdentity[]對應的Acl對象集合
public Map readAclsById(ObjectIdentity[] objects) throws NotFoundException;
//通過ObjectIdentity[]獲得僅適合于sids的Acl對象集合
public Map readAclsById(ObjectIdentity[] objects, Sid[] sids)
throws NotFoundException;
}
圖14-4展示了Acegi內置的AclService繼承鏈,處于這一繼承鏈中的各個接口及實現類各有各的用途。比如,JdbcAclService用于實現AclService策略接口。
圖14-4 AclService繼承鏈
MutableAclService用于維護Acl實例,開發者經常要同這一策略接口打交道,其定義如下。JdbcMutableAclService實現了MutableAclService。注意,開發者也可以提供O/R Mapping技術對應的AclService實現,比如Hibernate、JPA。Acegi僅僅實現了JDBC版本的AclService,開發者可以在自身的應用中同時使用O/R Mapping技術和JDBC。
//維護Acl實例
public interface MutableAclService extends AclService {
//在RDBMS中創建不含ACE的ACL,即Acl對象
public MutableAcl createAcl(ObjectIdentity objectIdentity)
throws AlreadyExistsException;
//從RDBMS中刪除objectIdentity對應的ACL
public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren)
throws ChildrenExistException;
//將現有的acl實例同步到RDBMS中
public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException;
}
通過本節內容,我們大致了解了Acegi提供的用于ACL子系統的各主要接口。本章后續內容將圍繞這些接口展開論述。
14.1.3 ACL權限的定義
我們可以對領域對象進行各種操作,比如新增、刪除、修改、瀏覽、管理等。Acegi將各種ACL權限信息建模在BasePermission對象中,相關的ACL權限信息摘錄如下。開發者經常需要同READ、WRITE、CREATE、DELETE、ADMINISTRATION等ACL權限打交道,這些權限的含義非常容易理解。借助于FieldRetrievingFactoryBean,開發者能夠在DI容器中配置它們。
public static final Permission READ =
new BasePermission(1 << 0, 'R'); // 1
public static final Permission WRITE =
new BasePermission(1 << 1, 'W'); // 2
public static final Permission CREATE =
new BasePermission(1 << 2, 'C'); // 4
public static final Permission DELETE =
new BasePermission(1 << 3, 'D'); // 8
public static final Permission ADMINISTRATION =
new BasePermission(1 << 4, 'A'); // 16
圖14-7展示了Acegi內置的Permission繼承鏈。BasePermission將基本的權限建模好了,而借助于CumulativePermission,開發者能夠建構復合權限。比如,我們可以對READ、WRITE等權限進行邏輯或運算,進而在RDBMS中存儲復合權限,從而簡化了ACL授權操作。
圖14-7 Permission繼承鏈
下面摘錄了ADMINISTRATION、READ、DELETE權限的定義示例,這些配置信息同樣摘自于applicationContext-common-authorization.xml配置文件。各個AclEntryVoter投票器和AbstractAclProvider子類需要引用到這些ACL權限定義。
<bean id="BasePermission.ADMINISTRATION"
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
<property name="staticField">
<value>org.acegisecurity.acls.domain.BasePermission.ADMINISTRATION</value>
</property>
</bean>
<bean id="BasePermission.READ"
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
<property name="staticField">
<value>org.acegisecurity.acls.domain.BasePermission.READ</value>
</property>
</bean>
<bean id="BasePermission.DELETE"
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
<property name="staticField">
<value>org.acegisecurity.acls.domain.BasePermission.DELETE</value>
</property>
</bean>
posted on 2007-07-03 19:24 junky 閱讀(1123) 評論(0) 編輯 收藏 所屬分類: security