3. 自主访问控制(DAC):权限模型的基础课

你好,欢迎来到第三章。

今天要聊的DAC,说白了就是“谁的东西谁说了算”。这是最贴近日常直觉的权限模型。你在Linux里敲chmod、在Windows里右键设置文件共享权限,都是在跟DAC打交道。我会先把原理讲透,再带你实操一下ACL和Linux的文件权限。说实话,我刚入行时花了很长一段时间才分清DAC和后面要讲的MAC、RBAC到底差在哪。我们一步步看。

3.1 DAC:资源归创建者

DAC(Discretionary Access Control,自主访问控制)的核心思想很简单:一个对象的创建者决定了谁能访问它。你可以自由地把权限“授予”或“收回”给其他用户。

我见过不少刚接触权限体系的人会问:“这不是理所应当的吗?”嗯,在80年代之前,很多系统采用的是完全集中管理的强制访问控制(MAC)。后来人们发现,完全由管理员替用户决定所有事,灵活性太差了。DAC因此被广泛采用。

它的授权判断流程大致是这样:

  1. 用户A创建了文件 report.txt。
  2. 系统把这个文件的所有者标记为A。
  3. 当用户B尝试访问时,系统检查A设置的权限条目。
  4. 如果条目允许,B通过;否则,拒绝。

这个过程中,“所有者”是授权的中心节点。你想想看,如果A给B开放了读权限,B就可以读了。A甚至可以把所有权转让给C。这很灵活,但也留下了很大的安全隐患。我稍后会在“缺点”里细说。

核心要素:
所有者(Owner):资源的直接创建者或受让人。
粒度:通常基于用户或用户组。
权限:读、写、执行、删除等。

3.2 ACL:实现DAC的“权限清单”

ACL(Access Control List,访问控制列表)是实现DAC最常见的手段。你可以把它理解成一张挂在每个资源上的“授权小纸条”。纸条上写着:“张三可以读,李四可以写,王五不能看。”

在Linux里,传统的文件权限是rwxr-xr-x这样的三位组,只针对“所有者”、“所属组”和“其他人”。这太粗了。如果我想只给用户“alice”读权限,不给同组的其他人?传统三位组办不到。这时候就需要ACL。

我给你看看实际的ACL表结构:

字段 说明 示例值
Entry Type 类型(用户、组、掩码等) user
Subject 主体标识(用户名或组名) alice
Permissions 权限位 r–
Inheritance 是否继承到子对象 true

我会在Linux实战部分演示ACL的用法。这里是ACL的工作流程图:

资源对象 (如 /data/project)
   |
   v
ACL 条目列表:
   user:alice   rw-
   user:bob      r--
   group:dev     rwx
   mask         rw-
   owner        webmaster
   other        ---
   |
   v
访问决定: 按顺序匹配用户 → 组 → 掩码 → other

我的一点经验:ACL的顺序很重要。系统从上到下匹配,匹配到第一个就生效。我曾经因为ACL条目顺序搞错,导致一个该有写权限的员工一直报错,排查了半天才发现是掩码(Mask)设得太低了。

3.3 DAC的“双刃剑”

任何事物都两面性。DAC的优点和缺点同样鲜明。我做了个对比表,一目了然:

方面 优点 缺点
灵活性 用户能自主授权,适应变化。 权限容易被“传递”或泄露。
管理成本 系统管理员负担减轻。 缺乏全局管控,容易出现配置错误。
推广 用户理解成本低,易接受。 难以应对恶意软件或内部威胁。

你会问:“那它到底适用于哪里?”

我个人的经验是:

  • 适用:个人文件管理、普通协作工作区、普通Web根目录。
  • 不适用:核心数据库、系统核心配置、金融交易日志、任何需要严格合规的数据。

你看,DAC就像一个“好人假设”模型——它假设所有者是理性的,不会乱授权。但现实中,“好人”也会犯错。“我曾经在部署一个共享文件夹时,为了省事直接给‘所有人’(other)开了写权限,结果一个实习生误删了半年的项目数据。从那以后,我再也不敢在DAC模式下轻易给other开放写权限了,除非有严格的审计和备份。”

3.4 典型场景一:Linux文件权限

这是DAC最集中、最经典的战场。我刚才提到了三种主体:Owner、Group、Other。权限位是rwx。但别以为它很简单。我来带你看看几个容易踩坑的点。

3.4.1 基本权限

# 查看权限
$ ls -l file.txt
-rw-r--r-- 1 root root 0 Jan  1 00:00 file.txt

# 修改权限(数字法)
$ chmod 644 file.txt   # 所有者读写,组和其他人只读

# 修改权限(符号法)
$ chmod u+x file.txt   # 给所有者加执行权
$ chmod o-w file.txt   # 收回其他人的写权

3.4.2 特殊位(SUID/SGID/Sticky Bit)

这三个是DAC的细节扩展:

  • SUID:文件运行时,获得文件所有者的身份。典型例子是/usr/bin/passwd。普通用户可以利用它临时变成root去修改自己的密码。
  • SGID:目录内创建的文件自动继承目录的组。
  • Sticky Bit:目录(如/tmp)内只能自己删自己的文件。
# 设置SUID
$ chmod u+s some_command

# 设置SGID
$ chmod g+s shared_directory

# 设置Sticky Bit
$ chmod +t /shared/tmp

# 查看特殊位
$ ls -l
drwxrwxrwt 2 root root 4096 Jan  1 00:00 /tmp

3.4.3 ACL实战操作

在Linux上,ACL需要acl包支持。当你遇到“我只想让userA可写,其他人(包括组内)只读”时,传统权限搞不定,ACL救场。

# 安装(如有必要)
$ sudo apt-get install acl   # Debian/Ubuntu

# 设置ACL:给用户alice赋予对file.txt的读写权限
$ setfacl -m u:alice:rw file.txt

# 查看ACL
$ getfacl file.txt
# file: file.txt
# owner: root
# group: root
user::rw-
user:alice:rw-
group::r–
mask::rw-
other::r–

# 移除用户alice的ACL
$ setfacl -x u:alice file.txt

注意:当你使用ACL后,ls -l显示的权限位后面会多一个+号。比如-rw-rw-r–+。ACL条目会被掩码(mask)约束。我曾经在调试一个共享文件夹的写权限时,发现通过setfacl给用户加了写权限,但程序仍然报错无权限。查了半天,发现是mask的值是r–。原因是一个同事用chmod改了目录的组权限,把mask挤掉了。切记:不要混用chmod和setfacl去修改同一个对象的组权限位,否则mask可能出问题。

3.5 一张图看懂DAC

我画了张SVG图,帮你把DAC的完整授权链路理清楚。

DAC:自主访问控制授权流程 资源对象(文件/目录) 所有者(创建者) ACL(权限列表) 访问者(用户B) 策略检查引擎 允许(Allow) 拒绝(Deny) 说明:所有者通过ACL定义规则;策略引擎按顺序匹配用户、组、掩码、其他,最终决定允许或拒绝

3.6 小结:DAC是基石,但别裸奔

现在你应该能理解DAC的全貌了。它简单、直观,是大多数操作系统和应用的默认权限模型。但就像我前面提到的“双刃剑”,如果企业业务对合规性、可审计性有硬性要求,DAC本身是不够的。你至少需要结合ACL做更精细的控制,或者直接上强制访问控制(MAC)或基于角色的访问控制(RBAC)。我之后会详细讲MAC和RBAC。

这一章的核心,就是让你在遇到“给谁开权限”的问题时,能立刻想到:“哦,这是DAC的范畴,我该用ACL来解决。” 别小看这一点,很多线上故障的根因,就是因为开发或运维在DAC层面给了过于宽泛或错误的授权。

我给你的建议:写个脚本,每天自动检查项目目录的ACL配置是否合规。特别是检查有没有“其他(other)”权限出现意外的w或x位。我把这个脚本跑在我的所有服务器上,它已经帮我预警了3次权限扩散事故。