文件和目錄的訪問控制


一、訪問控制列表

權限的概念相信你已經不陌生了,那么如何設置一個文件的訪問權限呢?編程可不可以實現動態的控制文件權限信息呢?答案是肯定的,.NET可以做到這些。

自由訪問控制列表(Discretionary Access Control ListDACL)(有時縮寫為ACL)是一種 Microsoft Windows NT 和更高版本用於保護資源(例如文件和文件夾)的機制。DACL包含多個訪問控制項(Access Control Entry,ACE)。訪問控制項將一個主體(通常是一個用戶賬戶或用戶賬戶組)與一個控制資源的使用的規則相關聯。通過DACL 和ACE,可以基於與用戶賬戶關聯的權限允許或拒絕資源的權限。例如,可以創建一個ACE,並將其應用於某個文件的DACL,以阻止除管理員以外的任何人讀取該文件。

系統訪問控制列表(System Access Control List,SACL)(有時稱為審核 ACE)是一種控制與資源關聯的審核消息的機制。與DACL相似,SACL包含定義指定資源的審核規則的 ACE。通過審核ACE,可以記錄訪問資源的成功嘗試或失敗嘗試,但與訪問ACE不同的是,審核ACE不控制哪些賬戶可以使用某個資源。例如,可以創建一個ACE並將其應用於某個文件的SACL,以記錄打開該文件的所有成功嘗試。

System.Security.AccessControl命名空間通過一些方便的類(這些類抽象化Windows ACL 安全系統的大部分復雜性)提供對訪問控制列表(ACL)的訪問。此外, System.Security.AccessControl命名空間還包含幾個提供對Windows ACL安全系統的高級訪問的類。

.NET Framework提供對下列資源的ACL的訪問:加密密鑰、目錄、事件等待句柄、文件、Mutexes、注冊表項、信號量。

上述每個資源都有幾個用於創建和修改ACL的類,本節主要關注目錄和文件的訪問控制。這些類如下:

DirectorySecurity類

該類表示目錄的訪問控制和審核安全。該類指定系統目錄的訪問權限以及訪問嘗試的審核方式。此類將訪問和審核權限表示為一組規則,每個訪問規則由一個FileSystemAccessRule對象表示,而每個審核規則由一個FileSystemAuditRule對象表示。

FileSecurity類

該類指定系統文件的訪問權限以及如何審核訪問嘗試。此類將訪問和審核權限表示為一組規則,每個訪問規則由一個 FileSystemAccessRule 對象表示,而每個審核規則由一個 FileSystemAuditRule 對象表示。使用該類可檢索、添加或更改表示文件的 DACL 和 SACL 的訪問規則。

DirectorySecurity類和FileSecurity類是對基礎Microsoft Windows文件安全系統的抽象。在此系統中,每個目錄都有一個自由訪問控制列表(DACL)和一個系統訪問控制列表(SACL),前者控制對目錄的訪問,后者指定要審核的訪問控制嘗試。FileSystemAccessRule和FileSystemAuditRule 類是對組成DACL和SACL的訪問控制項(ACE)的抽象。

二、添加訪問控制

對文件和目錄訪問控制的操作基本相同,對於同一種操作本書在通常情況下不重復舉例,讀者可自行實踐。

代碼清單7-9是一個簡單的示例,用來演示對文件添加訪問控制。

代碼清單 7-9          對文件添加訪問控制

using(FileStream file = new FileStream(@"E:\AclTest\acltest.txt", FileMode.Open, FileAccess.ReadWrite))

{

FileSecurity security = file.GetAccessControl();

FileSystemAccessRule rule = new FileSystemAccessRule(

new NTAccount(@"XuanHunComputer\xuanhun"), FileSystemRights.Read,

AccessControlType.Allow);

 security.AddAccessRule(rule);

file.SetAccessControl(security);
}

現在通過分析代碼清單7-9來了解控制添加單個文件訪問控制的細節。首先要做的是獲取對文件的訪問實例,這里使用FileStream,也許使用File或者FileInfo是你更喜歡的選擇。通過對調用GetAccessControl方法來檢索該文件的安全對象(類型為FileSecurity);除了包含其他內容以外,該對象還包含一組有序的訪問規則,它們共同確定了各種用戶和組對該文件所具有的權利。在該示例中,將一個新的訪問規則添加到FileSecurity對象中,以便向名為xuanhun的用戶授予文件的訪問權。在更改生效之前,必須將其持久保存在存儲器中。最后這個步驟是通過調用SetAccessControl方法完成的。

代碼清單7-9說明了如何向現有文件分配訪問權,那么如何在創建文件的初始就分配權限呢?這樣做有一個重要的安全原因:可確保安全的對象總是用一些默認的安全語義創建的。默認情況下,分層式資源管理器(例如文件系統或注冊表)中的對象從其父對象中繼承它們的安全設置,文件從它們的父目錄中繼承它們的安全設置。默認權利取決於所創建對象的類型,而且可能不是您所希望的那樣。例如,您很少會有意創建每個人都具有完全訪問權限的對象,但這卻可能恰好是默認安全設置所指定的權限。不能簡單地用默認安全設置創建對象並且在以后修改這些設置,產生此問題的原因是:在已經創建對象之后對其加以保護會打開一個機會窗口(在創建和修改之間),在此期間,該對象可能被劫持。劫持可能導致創建者失去對剛剛所創建對象的控制,這會造成災難性的后果。代碼清單7-10演示了在如何創建文件時配置訪問規則。

代碼清單 7-10             為新創建文件添加規則

 FileSecurity security = new FileSecurity();

            FileSystemAccessRule rule = new FileSystemAccessRule(
                new NTAccount(@"XuanHunComputer\xuanhun"), FileSystemRights.Read,
                AccessControlType.Allow);
            security.AddAccessRule(rule);
            FileStream file = new FileStream(
                @"M:\temp\sample.txt", FileMode.CreateNew,  FileSystemRights.Read,
                FileShare.None, 4096, FileOptions.None, security);

代碼清單7-10與代碼清單7-9執行的是相同的操作,但順序不同,並且無需持久保存更改(因為對象是全新的)。在創建文件之前,先創建一個FileSecurity對象,並且用所需的訪問規則填充它。隨后,FileSecurity實例被傳遞給文件的構造函數,該文件從一開始就被正確地加以保護。

三、訪問規則

訪問規則有兩種類型:“允許”(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類表示一個用戶或組賬戶。

四、審核規則

到目前為止,只是討論了訪問控制規則,它們構成了對象的DACL。DACL可以由對象的所有者任意更改,還可以由所有者已經給予其更改DACL權限的任何人更改。對象的安全描述符包含另一個規則列表,稱為系統訪問控制列表(System Access Control List,SACL),該列表將控制系統對對象執行哪個類型的審核。

審核是一種具有安全敏感性的操作。在Windows中,審核只能由本地安全機構(Local Security Authority,LSA)生成,因為LSA是唯一允許向安全事件日志(這里存儲了審核)中寫入項的組件。安全審核是一項非常嚴謹的業務,可以在計算機法庭中根據事實分析誰做了什么事情,以及誰試圖在系統中做什么事情。很多組織都長年保留它們的審核日志。不用說,規定對哪些項目進行審核的設置通常都受到嚴格的管理控制。如果執行該節中的代碼並且遇到UnauthorizedAccessException消息,可能是因為運行時所在的賬戶不包含“安全特權”(Security Privilege)。為了能夠修改甚至分析SACL,必須由本地計算機策略向你的賬戶分配這一強大的特權。盡管有這些可怕的警告,但在具有必要的特權之后,讀取和操作對象的審核設置在所有方面都類似於修改訪問控制設置。代碼清單7-13是一個操作審核規則的簡單示例。

代碼清單7-13 操作審核規則

using(FileStream file = new FileStream(
@"M:\temp\sample.txt",FileMode.Open, FileAccess.ReadWrite))
{
FileSecurity security = file.GetAccessControl();
FileSystemAuditRule rule = new FileSystemAuditRule(
new NTAccount( @"FABRIKAM\Full_Time_Employees"),
 FileSystemRights.Write, AuditFlags.Failure);
security.AddAuditRule(rule);
file.SetAccessControl(security)
}

與之前的代碼示例不同的是,本示例使用一個新的FileSystemAuditRule類。該類表示基礎訪問控制項(ACE)的抽象,該訪問控制項指定用戶賬戶、要提供的訪問的類型(讀、寫等),以及是否要執行審核。此類還可以指定如何從對象繼承審核規則以及將審核規則傳播到對象。

若要在 Microsoft Windows NT 上允許文件或目錄審核,必須在自己的計算機上啟用Audit Access Security策略。默認情況下,該策略設置為No Auditing。

啟用 Audit AccessSecurity 策略的步驟如下:

步驟 1     打開 Local Security Settings Microsoft 管理控制台 (MMC) 管理單元,定位於 Administrative Tools 文件夾中。

步驟 2     展開 Local Policies 文件夾,左擊 Audit Policy 文件夾。

步驟 3     在該 MMC 管理單元的右窗格上雙擊 Audit object access 項,或右擊並選擇屬性選項以顯示 Audit object access Properties dialog。

步驟 4     選中Success 或 Failure 框以記錄成功或失敗。

注意  用戶賬戶的審核規則需要同一用戶賬戶的對應訪問規則。

如代碼清單7-13所示,需要使用FileSystemAuditRule類創建新的審核規則,然后使用FileSecurity或DirectorySecurity類可持久保存此規則。

審核設置被表示為審核規則。可以指定你想要審核的安全主體(用戶或組)的名稱、感興趣的訪問權限類型(例如讀取、寫入等)以及你是希望在授予、拒絕訪問權限還是在執行這兩種操作時生成審核。例如,在代碼清單7-13中,每當全職雇員被拒絕對某個文件或給定父目錄下的目錄進行寫入訪問時,系統都將生成審核。繼承標志、傳播標志和保護設置對審核規則的作用方式與它們對訪問控制規則的作用方式完全相同。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM