第 7 讲:权限位——读、写、完全控制……
第 7 讲:权限位——读、写、完全控制……
卷一 · 发明权限(共 15 讲)
师生对话实录课:AI 当老师、我当 0 基础学生,每讲只发明一个概念。实验场 C:\Lab,本讲实测重跑于 2026-08-26(沙盒C:\Lab\permtest\)。
开场
🧑🏫 老师:
上一讲 Owner 回答了「这算谁的」。但协作里最常见的需求它答不了:
他能看、她能改、另一组能看但不能删、王五什么都能干还能把钥匙发给别人。
「主人全能 / 别人全不能」表达不了这种精细勾选。想象带密码锁的文件柜:柜门上能挂好几把钥匙给不同的人,但「钥匙」太粗——真实需求是把「操作文件柜」拆成一堆小开关,每人按需勾选。这些小开关就是权限位(permission bits)。
第 1 课:为什么叫「位」——它真的是一串二进制位
🧑🏫 老师:
拿到一个文件,你可能想做什么?看内容(读)、改内容(写)、运行它(执行)、看文件夹里有什么(列目录)、扔回收站(删除)、改只读/隐藏属性……Windows 把这些动作拆成了十几个最小颗粒——你在「属性 → 安全 → 高级」里看到的那堆勾选项,微软叫特殊权限。
「位」不是「位置」,是 bit。微软原话(Access Masks):
In an ACE, permissions are represented by one or more bits in a 32-bit value called an access mask. ... Each bit corresponds to an access right.
说人话:「读」是一个开关、「写」是另一个开关,各占 access mask 里的一位。勾上"读"就是把那一位置 1。GUI 里的"读取/写入/修改/完全控制"底层都是这些位的组合(套餐,第 3 课讲)。这个"位"的视角贯穿后面所有讲:ACE、访问检查,都是拿「令牌想要的位」和「DACL 里允许的位」做按位比对。
先记最常用的 5 个位(覆盖 90% 日常):
| 权限位 | 能干什么 | 一句话 |
|---|---|---|
| 读取数据 / 列出文件夹 | 看内容 / 看文件夹里有什么 | "能不能看" |
| 写入数据 / 创建文件 | 改内容 / 在文件夹里新建 | "能不能改/加" |
| 执行 / 遍历 | 运行程序;对文件夹叫"穿过" | "能不能跑/过" |
| 删除 | 删掉 | "能不能删" |
| 读取权限 | 看权限是怎么设的 | "能不能看门禁设置" |
🧑🎓 学生: 剩下的位里有没有名字会骗人的?
🧑🏫 老师:
两个,微软原文特意点名:
①「写入属性」不等于能建文件、能删文件。 官方:它「不代表能创建或删除文件/文件夹,只包含修改属性的能力」——改只读/隐藏那几个属性而已。要建文件得有「创建文件/写入数据」位,要删得有「删除」位。
②「删除子文件夹及文件」是个大招——能越过子项自己的权限。 官方:在父文件夹上有这个位,「即使子文件夹或文件本身没授予删除权限」也能删。同源文档还有一句更直白的:「对文件夹有完全控制的人,能删里面任何文件,不管文件自己的权限设成啥」。所以「删不删得掉一个文件」不只看文件自己的 ACL,还看它所在文件夹的 ACL。
第 2 课:套餐——Windows 打包好的勾选组合
🧑🏫 老师:
「属性 → 安全」里的读取 / 写入 / 修改 / 完全控制是套餐:常用位组合起名字打包。每个套餐勾了哪些位(据微软对照表):
| 套餐 | 大白话 | 勾了哪些位(要点) |
|---|---|---|
| 读取(R) | 只能看 | 读数据 + 读属性 + 读扩展属性 + 读权限 + 同步 |
| 写入(W) | 能写能建(不含读、不含删、不含执行) | 写数据/建文件 + 建文件夹/追加 + 写属性 + 读权限 + 同步 |
| 读取和执行(RX) | 能看 + 能运行/穿过 | 读取的全部 + 遍历/执行 |
| 修改(M) | 能看、能改、能删,但管不了权限、夺不了主 | RX 的全部 + W 的全部 + 删除 |
| 完全控制(F) | 全都能,还能改权限、删子项、夺主 | 全部 14 位(唯一含「删除子文件夹及文件」「更改权限」「取得所有权」) |
三个最容易踩的误区:
- 「写入」套餐不能读! 给某人「写入」,他并不能打开看内容。要"又能看又能改"得给「修改」;
- 「修改」能删但改不了权限。 要让人能调"谁能访问",得「完全控制」(或单独勾「更改权限」);
- 给了文件夹「完全控制」的人能删里面任何文件——不管子项权限设成啥(第 1 课那个大招)。
第 3 课:icacls 读权限——字母、位、继承标志
🧑🏫 老师:
GUI 点来点去太慢,命令行 icacls 一眼看清。本机刚建的文件:
PS> New-Item C:\Lab\permtest\fresh.txt -Value x -Force
PS> icacls C:\Lab\permtest\fresh.txt
C:\Lab\permtest\fresh.txt BUILTIN\Administrators:(I)(F)
NT AUTHORITY\SYSTEM:(I)(F)
BUILTIN\Users:(I)(RX)
NT AUTHORITY\Authenticated Users:(I)(M)每行一个 ACE(谁、什么权限、是否继承)。先认三样:
权限字母(套餐在命令行里的缩写,icacls 官表):N 无访问、F 完全控制、M 修改、RX 读取和执行、R 只读、W 只写、D 删除。还有一套更细的「高级权限」用括号写((RC) 读权限、(WDAC) 改权限、(DC) 删子项……),用到再查。
字母背后是哪些位? icacls 只给字母,看位的全名用 Get-Acl(翻成 .NET 的 FileSystemRights 枚举)。本机给五个文件各授一个字母、关继承,再读(真实输出):
F -> FullControl
M -> Modify, Synchronize
RX -> ReadAndExecute, Synchronize
R -> Read, Synchronize
W -> Write, Synchronize ← 注意:没有 Read!F 就是全位;其余各是几个位的组合、都带个 Synchronize(同步,多线程等句柄用,普通用户无感)。W 翻出来没有 Read——下一课的主角就是它。
继承标志——给文件夹授权时会带上「这条权限往下怎么传」。本机实测(在 demo_folder 上显式授 (M)):
C:\Lab\permtest\demo_folder JZFZ\chengongyi:(M) ← 本层显式授的(无 (I))
BUILTIN\Administrators:(I)(OI)(CI)(F)
NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
BUILTIN\Users:(I)(OI)(CI)(RX)| 标志 | 含义 |
|---|---|
(I) | 继承来的(Inherited),不是本层设的 |
(OI) | 对象继承:文件夹里的文件会继承这条 |
(CI) | 容器继承:子文件夹会继承这条 |
(IO) | 只继承:这条只往下传、对本对象自己不生效 |
(NP) | 不再传播:只传给直接子项,不往下嵌套 |
排查「这权限哪来的」,先看有没有 (I)——有就去父目录找源头,没有就是本层显式设的。
第 4 课:实验——「写入」套餐到底能不能读?
🧑🏫 老师:
「写入不含读」「写入其实能写」这两条最反直觉,四步验证。先造一个只有 (W) 的文件(/inheritance:r 关继承丢弃继承项 + /grant:r 重置成只含我 (W),第 6 讲讲过的两个 r):
① 读——被拒。
PS> Get-Content C:\Lab\permtest\ro.txt
Get-Content : 对路径"…"的访问被拒绝。Get-Acl 翻它只有 Write, Synchronize——(W) 不含「读取数据」位。「写入」确实不能读,实锤。(顺带:我是这文件的 owner,但上一讲说过 owner 只隐式带「改 DACL / 读安全描述符」,不带读数据。)
② 写——真能写。 .NET AppendAllText 只写方式追加:
PS> [System.IO.File]::AppendAllText("$sb\wo.txt", ' WORLD') # 不报错
PS> icacls … /grant:r 'jzfz\chengongyi:(F)' # 临时加回 F 才能回读
PS> Get-Content …
hello WORLDhello 变成了 hello WORLD——(W) 允许写,只是不允许读。它不是"坏的写",是"只写不读"。
③ 一个真实坑:Set-Content 在 (W) 下也写不了。
PS> Set-Content "$sb\wp.txt" 'ps'
Set-Content : 对路径"…"的访问被拒绝。②刚证过 (W) 能写,Set-Content 却被拒——PowerShell 的 Set-Content/Add-Content 以读+写模式打开文件,光有"写数据"位不够。权限位是按「打开文件时要的访问类型」逐位卡的,工具要的位不全,照样进不去(第 6 讲实验一第 5 步埋的就是这个梗)。
④ 对照:(RX) 能读。
PS> Get-Content "$sb\rx.txt"
hello四步对账:
| 步 | 文件权限 | 操作 | 真实结果 | 证明什么 |
|---|---|---|---|---|
| ① | (W) | Get-Content 读 | 被拒 | 「写入」不含读 |
| ② | (W) | .NET AppendAllText 写 + 回读 | hello WORLD | (W) 真的允许写 |
| ③ | (W) | Set-Content 写 | 被拒 | 工具"读+写"打开,位不全照样被卡 |
| ④ | (RX) | Get-Content 读 | hello | 「读取」套餐才含读 |
一句话收口:「写入」套餐 = 只写不读。不少写文件的程序(
Set-Content、各种"打开再保存"的编辑器)一上来就要"读+写",只给「写入」时它们反而写不了——不是权限设错了,是位没给全。
插问:两条铁律——为什么权限总"和我以为的不一样"?
🧑🎓 学生: 有没有几条总规则,能解释大部分"权限怪象"?
🧑🏫 老师:
两条,微软原话背书:
铁律一:没给,就是拒绝。("When permission to perform an operation is not explicitly granted, it is implicitly denied.")默认啥都不给,谁都没提的动作一律拒绝——不是被谁挡了,是压根没人给你开门。
铁律二:你亲手设的,压过继承来的。("Explicit permissions take precedence over inherited permissions, even inherited Deny permissions.")在这个文件夹自己上显式设了"允许张三读取",从上层继承下来的"拒绝张三"就挡不住他。注意这条只讲「显式 vs 继承」;显式 Allow 和显式 Deny 同时存在时 Deny 赢——冲突的逐条裁决是第 10 讲「访问检查」的事。
再送一个高频坑:共享权限和 NTFS 权限,取更严的。 从网络访问共享文件夹时,最终权限由两套共同决定,取更严格的那个生效。经典踩坑:NTFS 给了"完全控制"、共享权限还是默认"读取"——对方通过网络只能读。区分:NTFS 权限本地、网络都管;共享权限只管网络。老运维的省心做法:共享权限一律「Everyone 完全控制」,所有限制全交给 NTFS——只维护一套。
附:14 个特殊权限全表(用到再查)
| 特殊权限 | 能干什么 |
|---|---|
| 遍历文件夹 / 执行文件 | 穿过文件夹走到里面(即使对经过的文件夹没权限);对文件是运行 |
| 列出文件夹 / 读取数据 | 看文件夹里有什么;对文件是看内容 |
| 读取属性 | 看只读、隐藏属性 |
| 读取扩展属性 | 看自定义扩展属性 |
| 创建文件 / 写入数据 | 文件夹里新建;对文件是改内容 |
| 创建文件夹 / 附加数据 | 新建子文件夹;对文件是只能末尾追加 |
| 写入属性 | 改只读、隐藏属性(不含建/删) |
| 写入扩展属性 | 改扩展属性(不含建/删) |
| 删除子文件夹及文件 | 删里面的子项(哪怕子项没给删除权限) |
| 删除 | 删自己(父文件夹有"删除子项"时也能删) |
| 读取权限 | 看权限怎么设的 |
| 更改权限 | 改权限 |
| 取得所有权 | 把 owner 变成自己 |
| 同步 | 多线程等句柄用,普通用户无感 |
收束
你现在会了:
- 权限位——把"能做什么"拆成 access mask 里的一位位;套餐(R/W/RX/M/F)只是位的组合。
- 反直觉三连——「写入属性」不含建/删;「删除子文件夹及文件」能越过子项权限;「写入」不含读(四步实验实锤:W 下读拒、AppendAllText 写成、Set-Content 因读写打开被拒、RX 能读)。
- 两条铁律——没给就是拒;显式压过继承。
icacls字母 +(I)(OI)(CI)(IO)(NP)标志;Get-Acl看位全名(F→FullControl、W→Write, Synchronize…)。- 网络访问 = 共享权限与 NTFS 取更严。
下一讲才需要: 人一多,不能对每个人单独维护时怎么办——组(Groups)。
← 上一章:第 6 讲:Owner
· 回书稿索引
→ 下一章:第 8 讲:组