需分别调用addaccessrule(dacl)和addauditrule(sacl)并一次性setaccesscontrol提交;sacl生效依赖系统审核策略开启、账户具备seauditprivilege权限及正确配置inheritanceflags。

怎么用 FileSecurity 同时设置 DACL 和 SACL
不能只调用一次 SetAccessControl 就完事——DACL 和 SACL 是两个独立的 ACL 对象,必须分别构造、分别附加。常见错误是只改了 GetAccessRules 返回的规则却忘了调用 AddAccessRule 或 AddAuditRule,结果写入时只生效一半。
- 先用
new FileSecurity()创建空对象,再分别调用AddAccessRule()(设 DACL)和AddAuditRule()(设 SACL) - 务必在最后调用
File.SetAccessControl(path, fileSecurity)一次性提交,不要分两次调用 - 如果路径已存在且继承了父目录权限,记得用
SetAccessRuleProtection(true, false)断开继承,否则你的规则可能被覆盖
FileSystemAccessRule 和 FileSystemAuditRule 的权限值怎么选
DACL 用 FileSystemAccessRule,SACL 用 FileSystemAuditRule,两者参数看似一样,但底层语义完全不同:前者控制“能不能做”,后者只决定“做了要不要记日志”。权限位(如 FileSystemRights.ReadData)可以相同,但 AuditFlags 必须明确指定是 Success、Failure 还是两者都记。
- 审计规则里
AuditFlags.Failure不代表“禁止操作”,它只是说失败时记日志;真正禁止靠 DACL 里的AccessControlType.Deny -
FileSystemRights.FullControl在 SACL 中不推荐直接使用——太宽泛,容易刷爆安全日志;优先拆成ReadData、WriteData等细粒度项 - 注意
InheritanceFlags和PropagationFlags:子文件/文件夹是否继承审计规则,和 DACL 是两套独立开关
为什么设置了 SACL 却没日志?常见排查点
Windows 审计策略本身没开,或者当前用户没权限写入安全日志,SACL 就完全静默。这不是代码问题,而是系统级依赖。
- 确认本地组策略已启用:「计算机配置 → Windows 设置 → 安全设置 → 本地策略 → 审核策略」中,“审核对象访问”必须设为“成功”或“失败”或两者
- 运行代码的账户必须有
SeAuditPrivilege权限(通常管理员才有),普通用户即使代码跑通也不会生成日志 - 事件查看器里看「Windows 日志 → 安全」,筛选事件 ID 4663(对象访问);如果一条都没有,大概率是策略或权限没到位,不是 C# 写错了
用 GetAccessRules 查 DACL/SACL 时容易漏掉的细节
这个方法返回的是 AuthorizationRuleCollection,但它默认只查当前对象的显式规则,不包含继承来的规则——而实际生效的权限往往是合并结果。更麻烦的是,DACL 和 SACL 必须分开查,参数稍错就拿错集合。
- 查 DACL:用
fileSecurity.GetAccessRules(true, true, typeof(NTAccount)),第三个参数必须是typeof(NTAccount)(不能是typeof(SecurityIdentifier)),否则返回空 - 查 SACL:必须用
fileSecurity.GetAuditRules(true, true, typeof(NTAccount)),函数名是GetAuditRules,不是GetAccessRules - 返回的规则里,
IdentityReference是字符串形式(如"BUILTIN\Administrators"),别直接当对象用;需要比对时建议转成Sid再比较
真正难的不是加几条规则,而是理解 DACL 控制行为、SACL 仅触发日志、而系统策略和账户权限才是日志能否落地的前提。少一个环节,整套机制就哑火。










