ABAC 在 C# 文件系统中不原生支持
Windows 文件系统(NTFS)本身只支持 DAC(自主访问控制)和少量 MAC(强制访问控制)扩展,
FileSystemAcl、
File.SetAccessControl这类 API 操作的全是 SID + 权限位(如
FileSystemRights.Read),没有属性断言、策略引擎或上下文评估能力。ABAC 的核心——“根据用户属性、资源属性、环境属性动态决策”——C# 标准库根本不提供对应抽象。
手动实现 ABAC 策略评估器的关键三步
你得自己写一个轻量策略引擎,不能依赖
WindowsIdentity或
PrincipalPermission——它们只认角色/组,不认属性。重点不是“怎么授权”,而是“在哪个环节插入判断”。 在文件操作前拦截:比如封装
File.ReadAllText为
SecureFile.ReadAllText,调用前先走策略评估 定义属性契约:统一用
IDictionary<string object></string>表达主体(用户部门、安全等级)、资源(文件标签、分类、创建时间)、环境(是否内网、请求时间、客户端 IP) 策略规则用表达式树或简单 JSON 描述:例如
{"resource.tag": "confidential", "subject.clearance": ">=5"},避免硬编码 if-else
别直接改 NTFS ACL——那是自找麻烦
有人试图把 ABAC 决策结果反向写成
FileSystemAccessRule,给每个用户动态生成 ACL 条目。这会快速触达 Windows 单文件 ACL 条目上限(约 1024 条),且属性变更后无法自动清理旧规则,
GetAccessControl返回的
AuthorizationRuleCollection也难以可靠匹配更新。 ACL 是静态快照,ABAC 是实时计算——混用等于把动态逻辑压进静态结构 权限继承、所有者变更、域策略推送都会让手动生成的 ACL 失效或冲突 真正该记录的是策略日志:
PolicyDecisionLog.Write("file://report.pdf", "DENY", "subject.role=guest AND resource.sensitivity>3")
用 ClaimsPrincipal
做属性载体最省事
ClaimsPrincipal天然支持多属性(
Claim),能从 JWT、AD FS 或本地配置加载,比自定义
UserContext类更易集成现有认证流。但注意它不参与 NTFS 检查——你得显式调用策略评估。
var policy = new AbacPolicy();
var decision = policy.Evaluate(
Thread.CurrentPrincipal as ClaimsPrincipal,
new ResourceAttributes { Path = @"C:\data\q3.xlsx", Tag = "financial" },
new EnvironmentAttributes { ClientIp = "10.1.2.3", TimeOfDay = DateTime.Now.Hour }
);
if (decision != AccessDecision.Permit) throw new UnauthorizedAccessException();关键点:
AbacPolicy.Evaluate必须是你自己写的,.NET 没有
AbacPolicy类;
AccessDecision也得自己定义枚举,别指望
System.Security提供 ABAC 语义。
复杂点在于策略一致性——比如“审计员可看所有
tag=audit文件”这条规则,必须在所有文件入口点(Web API、WinForms 打开对话框、后台服务扫描)都触发同一套评估逻辑,漏掉一个就等于留了后门。
