使用FileSystemSecurity/DirectorySecurity时如何设置GENERIC_ALL等非FileSystemRights访问掩码
解决方案
方案1:通过反射绕过公开构造函数校验
FileSystemAccessRule的公开构造函数的校验逻辑仅存在于输入参数验证阶段,内部实际存储权限的字段支持完整的32位访问掩码。我们可以通过反射直接初始化实例,跳过校验:
using System.Reflection; using System.Security.AccessControl; using System.Security.Principal; // 目标安全标识,可按需替换为你需要的用户/用户组标识 IdentityReference identity = WindowsIdentity.GetCurrent().User; // 显式指定GENERIC_ALL掩码 const int GENERIC_ALL = 0x10000000; InheritanceFlags inheritanceFlags = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit; PropagationFlags propagationFlags = PropagationFlags.None; AccessControlType accessType = AccessControlType.Allow; // 反射获取支持传入原始int掩码的非公开构造函数 ConstructorInfo ctor = typeof(FileSystemAccessRule).GetConstructor( BindingFlags.Instance | BindingFlags.NonPublic, new[] { typeof(IdentityReference), typeof(int), typeof(bool), typeof(InheritanceFlags), typeof(PropagationFlags), typeof(AccessControlType) } ); FileSystemAccessRule rule = (FileSystemAccessRule)ctor.Invoke(new object[] { identity, GENERIC_ALL, false, inheritanceFlags, propagationFlags, accessType });
构造得到的规则可以正常添加到DirectorySecurity或者FileSystemSecurity的访问规则集合中,不会触发校验错误,最终生成的ACE访问掩码就是你需要的0x10000000。
方案2:通过CommonAce直接构造ACE(无需反射)
如果你不想依赖非公开API,可以直接构造CommonAce实例,再添加到安全描述符的ACL中,该方法完全使用公开API实现:
using System.Security.AccessControl; using System.Security.Principal; IdentityReference identity = WindowsIdentity.GetCurrent().User; const int GENERIC_ALL = 0x10000000; InheritanceFlags inheritanceFlags = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit; PropagationFlags propagationFlags = PropagationFlags.None; AccessControlType accessType = AccessControlType.Allow; // 直接构造ACE,支持传入原始访问掩码 CommonAce ace = new CommonAce( AceFlags.None | (AceFlags)inheritanceFlags | (AceFlags)propagationFlags, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, GENERIC_ALL, identity, false, null ); // 将ACE添加到目录/文件的自由访问控制列表中 DirectorySecurity security = new DirectorySecurity(); security.DiscretionaryAcl.AddAce(ace);
该方案生成的ACL和直接添加FileSystemAccessRule效果完全一致,且访问掩码会保留你传入的GENERIC_ALL值。
注意事项
两种方案都绕过了.NET对FileSystemRights的枚举范围校验,你需要自行保证传入的访问掩码符合Windows访问控制模型的规范,避免生成无效的ACE导致权限异常。
内容的提问来源于stack exchange,提问作者0xC0000022L
相关产品推荐
相关产品推荐

