訪問規則有兩種類型:“允許”(allow)和“拒絕”(deny)。可以通過檢查規則的AccessControlType屬性來確定相應規則的類型。按照約定,拒絕規則總是優先於允許規則。因而,如果向某個對象中添加下列兩個規則:“授予每個人讀、寫訪問權限”和“拒絕Xuanhun寫訪問權限”,則Xuanhun將被拒絕進行寫訪問。
想要枚舉文件或者目錄的訪問規則時,可以使用如代碼清單7-11所示的方式。
7-11 枚舉文件訪問規則
class Program { static void Main(string[] args) { string path = @"e:\AclTest\acltest.txt"; FileSecurity security = File.GetAccessControl(path); foreach (FileSystemAccessRule rule in security.GetAccessRules(true, true, typeof(NTAccount))) { Console.WriteLine("{0} {1}---- {2}", rule.AccessControlType == AccessControlType.Allow ? "授權" : "拒絕",rule.IdentityReference.ToString(), rule.FileSystemRights ); } Console.Read(); } }
以上代碼使用File類的GetAccessControl方法獲取FileSecurity對象,然後通過FileSecurity類的GetAccessRules方法獲取當前文件的訪問規則。對於目錄的操作與此基本類似,相應地,使用的是DirectorySecurity對象。
GetAccessRules方法有三個參數:第一個參數表示是否要包括為對象顯式設置的訪問規則;第二個參數表示是否要包括繼承的訪問規則;第三個參數表示訪問規則的類型。代碼清單7-11的運行結果如圖7-9所示。
7-9 枚舉文件訪問規則的運行結果
為方便起見,訪問規則被公開為集合。該集合是只讀的,因此對它的規則進行的所有修改都必須通過FileSecurity對象的專用方法(例如AddAccessRule、SetAccessRule和RemoveAccessRule)執行。集合內部的規則對象也是不可改變的。要了解為什麼拒絕規則優先於允許規則,必須知道訪問檢查算法是如何工作的。當執行訪問權限檢查時,將按照規則在訪問控制列表內部出現的順序對它們進行評估。在代碼清單7-11中,當檢查用戶Xuanhun的訪問權限時,會首先評估拒絕Xuanhun讀取訪問的規則,然後再評估授予BUILTIN\Everyone讀取和執行訪問權限的規則。一旦做出允許或拒絕的決策,評估就將停止。這就是拒絕規則“生效”的原因。如果它們被放置在允許規則之後,則它們不會總是執行它們的預期功能。
和可以添加新的訪問規則一樣,還可以移除現有的訪問規則。但是注意,在從用戶那裡撤回某項權限和完全拒絕該權限之間存在差異。例如,假設Xuanhun是“全職雇員”組的成員,並且被設置為:“全職雇員可以讀取文件”和“Xuanhun具有讀寫訪問權限”。根據這一方案,撤消Xuanhun的讀取權利會產生下列規則:“全職雇員可以讀取文件”和“Xuanhun具有寫入訪問權限”。這恐怕不是您所期望的結果,因為撤消Xuanhun的讀取訪問權限沒有產生任何效果:Xuanhun仍然可以作為全職雇員獲得讀取訪問權限。如果你的目標是確保不會將訪問權限授予Xuanhun,達到該目標的唯一方式是添加一個拒絕規則。此外,如果該對象根本不包含任何訪問規則,那麼每個人都將被拒絕對該對象的所有訪問權限。
繼承
我們只考慮了不具有子對象的簡單的葉子對象。一旦從葉子對象(例如文件、信號量和互斥鎖)轉向容器對象(例如目錄、注冊表項和Active Directory容器),事情就變得復雜了。額外的復雜性源自以下事實:容器的訪問規則可能被配置為不僅應用於對象本身,而且還應用於它的子對象、子容器或這兩者。這就涉及繼承和傳播設置的領域。
每個訪問規則不是顯式的就是繼承的(用IsInherited屬性來確定),顯式規則是那些已經通過在對象上執行的顯式操作添加到該對象的規則;相反,繼承規則來自於父容器。在使用對象時,只能操縱它的顯式規則。
在向容器中添加新的顯式規則時,可以指定兩組標志:繼承標志和傳播標志。繼承標志有兩個:容器繼承(Container Inherit,CI)和對象繼承(Object Inherit,OI)。指定容器繼承的規則將應用於當前容器對象的子對象,對象繼承規則應用於葉子子對象。當傳播標志被設置為None時,這些關系是可傳遞的:它們將跨越當前容器下層次結構的整個子樹,並且應用於該容器的子對象、孫子對象等。
規則的順序是很重要的,因為它確定了優先順序,並最終影響到對象的訪問方式。盡管無法更改默認順序,但明白一組規則將被授予哪個類型的訪問權限是很重要的。最重要的是,所有繼承規則總是跟在顯式規則後面。這樣,顯式規則總是優先於繼承規則,父規則優先於祖父規則,等等。
父對象和子對象
如果希望對象避開由其父對象給予它的安全語義,會發生什麼情況呢?實際上,確實存在可以聲明“我的父對象的安全設置將不再適用於我”的機制。此時,甚至可以指定是否希望在該情況下使繼承規則保持原樣,但是在父對象的設置發生更改時拒絕“偵聽”,另外,可以徹底清除所有繼承規則。這是通過訪問控制保護實現的,如代碼清單7-12所示:
7-12 訪問控制保護
using(FileStream file = new FileStream( @"M:\temp\sample.txt", FileMode.Open, FileAccess.ReadWrite)) { FileSecurity security = file.GetAccessControl(); security.SetAccessRuleProtection( true, false ); file.SetAccessControl(security);}
以上代碼中需要說明的是SetAccessRuleProtection方法,該方法設置或移除與此ObjectSecurity 對象關聯的訪問規則的保護。受保護的審核規則不會通過繼承被父對象修改。它的第一個參數標識訪問規則是否被繼承,如果為true則不被繼承,否則繼承。第二個參數標識是否保留繼承的訪問規則,如果保留為true,去除則為false。
注意 盡管可以使用該技術避免從父對象那裡收到繼承設置,但沒有辦法收到父對象不打算給予你的繼承設置,傳播只會發生在其ACL沒有受到保護的對象上。可以做的唯一事情就是在父對象改變主意之前獲得繼承設置的快照,因為一旦訪問規則受到保護,它們就將保持這個狀態,並且父對象無法重寫它們。
所有者
“所有者”(owner)的概念對於對象安全性是很特殊的。所有者被賦予了特殊的權力,即使與對象相關聯的規則禁止用戶訪問該對象,但如果該用戶是所有者,則他仍然可以重寫現有規則,並重新獲得對該對象的控制。完成該操作的過程與訪問規則的常規操作過程沒有什麼不同。安全對象還允許更改所有者,但是操作系統將禁止其他人執行該操作。通常,為了更改所有者,必須具有對象的TakeOwnership權限或者具有特殊的“取得所有權”(Take Ownership)特權更改所有者如下所示(假設你具有這樣做的權利):
FileSecurity security = file.GetAccessControl();
security.SetOwner(new NTAccount(@"Administrators\Xuanhun"));
file.SetAccessControl(security);
以上代碼中使用SetOwner方法來制定當前文件的所有者為NTAccount類型用戶Xuanhun。
此外,還可以查看對象的當前所有者是誰,或者請求將所有者作為安全標識符或Windows NT賬戶對象返回,如以下代碼所示:
SecurityIdentifier sid = (SecurityIdentifier)security.GetOwner(typeof(SecurityIdentifier));
Console.WriteLine(sid.ToString());
NTAccount nta = (NTAccount)security.GetOwner(typeof(NTAccount));
Console.WriteLine(nta.ToString());
以上代碼使用兩種形式來查看所有者:一種是SecurityIdentifier對象,另一種是NTAccount對象。SecurityIdentifier類表示一個安全標識符 (SID) 並為 SID 提供封送處理和比較操作。NTAccount類表示一個用戶或組賬戶。
作者:玄魂
出處:http://www.cnblogs.com/xuanhun/
查看本欄目