Windows 如何解决文件系统冲突 permissions/rights?

How does Windows resolve conflicting FileSystem permissions/rights?

在Windows的安全体系中,一个用户可以属于多个组,一个组又可以包含其他组。 'rules' 在 Windows 中解决权限冲突的方法是什么?

例如,假设用户在 A 组和 B 组中。A 组有 'Deny Read' 个文件,而 'Group B' 有 'Allow Read'。用户可以读取文件吗?

如果用户本身被拒绝阅读某些内容的权利,但它所在的组明确允许该权限怎么办?

虽然我知道如何通过 AccessRules 获取特定文件系统资源的权限以及它们公开的权限,但由于规则针对的是特定的 IdentityReference,它可能是用户或组,我已经看到冲突并正在尝试确定逻辑找出'who wins'.

...或者是否有一种已知的方式说 'Get me all rights for this user, also taking into consideration any memberships' 并让系统担心它? (我很惊讶我还没有找到确切的答案。我正在做的事情看起来工作量很大。)

var Identity = WindowsIdentity.GetCurrent();
var fileInfo = new FileInfo(@"C:\Code\Path\To\Some\File.txt");

// Get all identity references for this user (user's and it's groups)
var identityReferences = new HashSet<IdentityReference>();
identityReferences.Add(Identity.User);
foreach(var group in Identity.Groups)
    identityReferences.Add(group);

// Get all rules for this user on this specific FileInfo
var fileSystemAccessRules = fileInfo.GetAccessControl()
    .GetAccessRules(true, true, typeof(SecurityIdentifier))
    .OfType<FileSystemAccessRule>()
    .Where(rule => identityReferences.Contains(rule.IdentityReference));

FileSystemRights allowedUserRightsMask = 0;
FileSystemRights deniedUserRightsMask  = 0;

// Get mask of all granted, and all denied rules
foreach(var fileSystemAccessRule in fileSystemAccessRules)
{
    var ruleRights = fileSystemAccessRule.FileSystemRights;

    var relevantUserRightsMask = (fileSystemAccessRule.AccessControlType == AccessControlType.Allow)
        ? allowedUserRightsMask
        : deniedUserRightsMask;

    relevantUserRightsMask |= ruleRights;
}

// Do something with the final user rights mask here.

Understanding Windows NTFS Permissions所述权限优先级如下:

  1. 明确拒绝
  2. 明确允许
  3. 继承拒绝
  4. 继承允许

因此,回答您的问题:视情况而定。明确拒绝总是优先的;继承拒绝,但是,"loses" 到显式允许。

有关此影响的更多详细信息,请参阅文章。

优先级由 ACE 的顺序决定,如 MSDN 中奇怪命名的 How AccessCheck Works 中所述:

The system examines each ACE in sequence until one of the following events occurs:

An access-denied ACE explicitly denies any of the requested access rights to one of the trustees listed in the thread's access token.

One or more access-allowed ACEs for trustees listed in the thread's access token explicitly grant all the requested access rights.

All ACEs have been checked and there is still at least one requested access right that has not been explicitly allowed, in which case, access is implicitly denied.

DACL 中的 ACE 也有一个标准的出现顺序,如 Order of ACEs in a DACL. If the permissions have been set by the built-in Windows tools, the ACEs will be in this order, which is how you get the rules Esteban described in his answer (see referenced article) 中所述。但是请注意,DACL 并不 遵循此标准。应用程序可以设置不这样做的 DACL - 虽然这样做通常是不明智的,因为它会混淆 Windows GUI。

(请注意,某些 API 可能会自动将 ACL 中的 ACE 重新排序为标准顺序;如果您需要保留 ACL 中 ACE 的实际顺序,请确保您使用的是 API 不会这样做。)

使事情复杂化的是,还有其他规则,例如对象的所有者已隐式授予 READ_CONTROLWRITE_DAC,并且还有其他受托人,例如 INTERACTIVE 在典型的访问令牌中,与组成员资格无关。

通常,正确的行为是而不是尝试确定您拥有的访问权限,而是简单地尝试您想要采取的任何操作并在失败时处理错误. (特别要记住,访问文件可能因访问权限以外的原因而失败,例如因为文件正在被另一个进程使用。)

但是,在极少数情况下您确实需要确定适用的访问权限,您可以使用 AuthzAccessCheck() function. Sample code is available in the documentation on the (deprecated and inaccurate) GetEffectiveRightsFromAcl() 函数来实现。

(我对 .NET 不够熟悉,无法确定它是否包含内置等效项;我猜它没有。但是,如果需要,您可以 P/Invoke。)