4、用户与权限管理
Linux 系统的安全模型建立在“用户—组—权限”三层体系之上。用户是访问控制的实体,组是权限分配的集合,而权限则定义了实体对文件或目录的可执行操作边界。在计算机四级考试与真实运维场景中,用户与权限管理不仅是命令的记忆,更是对 Linux 安全策略设计思路的检验。本章将围绕用户/组管理、密码策略、sudo 机制、ACL 访问控制列表及特殊权限五大核心模块展开,结合命令实操与案例复盘,帮助您建立系统化的权限管理知识框架。
4.1 用户与组管理:从命令到底层文件
4.1.1 核心原理:用户与组的映射关系
Linux 系统中,用户账号信息存储于 /etc/passwd,密码密文存储于 /etc/shadow,组信息存储于 /etc/group。每个用户通过唯一的 UID(用户标识号)被内核识别,而组通过 GID(组标识号)进行权限聚合。用户与组之间是多对多的关系:一个用户可以属于多个组,其中“初始组”在创建时指定,“附加组”通过 usermod -G 追加。理解这一映射关系是权限管理的基础,因为文件权限中的“属主、属组、其他”三个维度正是基于 UID 和 GID 进行匹配的。
4.1.2 操作流程:用户与组的生命周期管理
| 操作类型 | 命令示例 | 关键参数说明 | 底层文件变更 |
|---|---|---|---|
| 创建用户 | useradd -m -G wheel -s /bin/bash alice | -m 创建家目录;-G 附加组;-s 指定 shell | /etc/passwd、/etc/shadow、/etc/group、/home/alice |
| 修改用户 | usermod -L alice(锁定) | -L 锁定;-U 解锁;-aG 追加组 | /etc/shadow 中密码字段前加 ! |
| 删除用户 | userdel -r alice | -r 同时删除家目录和邮件池 | 移除上述文件中的相关记录 |
| 创建组 | groupadd -g 5000 devteam | -g 指定 GID,避免自动分配冲突 | /etc/group、/etc/gshadow |
| 修改组 | groupmod -n newname devteam | -n 重命名组 | /etc/group 中组名变更 |
useradd -D 查看默认值,并通过 /etc/login.defs 预设 UID 范围(通常 1000-60000)、密码过期天数等参数。对于服务账号(如 nginx、mysql),应使用 -M 不创建家目录,并设置 -s /sbin/nologin 禁止登录,降低安全风险。
4.1.3 案例拆解:批量创建项目组用户
场景:某公司新成立“数据平台”项目组,需要为 5 名工程师创建账号,统一加入 data_team 组,并要求所有用户使用 bash shell、家目录位于 /home 下。
# 1. 创建组(指定 GID 避免冲突)
groupadd -g 5200 data_team
# 2. 批量创建用户并加入组
for user in zhangsan lisi wangwu zhaoliu sunqi; do
useradd -m -G data_team -s /bin/bash "$user"
echo "$user:InitialPass123" | chpasswd # 设置初始密码
chage -d 0 "$user" # 强制首次登录修改密码
done
# 3. 验证
grep data_team /etc/group
id zhangsan
复盘:通过 chage -d 0 强制首次登录改密,避免初始密码长期有效;使用 chpasswd 批量设置密码比交互式 passwd 更高效。若需临时禁用某用户,使用 usermod -L 而非删除,保留数据便于后续审计。
4.1.4 常见误区与总结
- 误区一:直接编辑
/etc/passwd修改用户信息。正确做法是使用usermod,因为直接编辑容易导致文件格式错误或缓存不一致。 - 误区二:混淆
useradd与adduser。在 CentOS/RHEL 中adduser是useradd的符号链接;在 Debian/Ubuntu 中adduser是交互式脚本,行为不同。 - 误区三:忽略 UID 复用风险。删除用户后若立即创建新用户,系统可能复用原 UID,导致旧文件属主变为新用户,造成权限泄露。
4.2 密码策略:入口安全的第一道防线
4.2.1 核心原理:影子密码与老化机制
现代 Linux 使用 /etc/shadow 存储加密密码,字段以冒号分隔,共 9 个字段:用户名、加密密码、最后一次修改时间、最小修改间隔、最大有效天数、警告天数、宽限天数、失效日期、保留字段。密码策略的核心在于通过 chage 命令和 /etc/login.defs 文件控制密码的生命周期,防止密码长期不变带来的暴力破解风险。
4.2.2 操作流程:制定并实施密码策略
- 设置全局默认值:编辑
/etc/login.defs,设置PASS_MAX_DAYS 90、PASS_MIN_DAYS 7、PASS_WARN_AGE 14。 - 配置复杂度要求:通过 PAM 模块
pam_pwquality.so,在/etc/pam.d/system-auth中设置minlen=12、dcredit=-1(至少一个数字)、ucredit=-1(至少一个大写字母)。 - 对单个用户实施策略:使用
chage -M 90 -m 7 -W 14 alice设置最大有效天数、最小间隔和警告天数。 - 查看策略:
chage -l alice显示当前用户的密码老化信息。
4.2.3 案例拆解:等保三级密码策略落地
背景:某政务系统需满足等保三级要求,密码策略必须包含:90 天更换、复杂度四级、连续失败 5 次锁定账号 30 分钟。
# 1. 修改 /etc/login.defs
sed -i 's/^PASS_MAX_DAYS.*/PASS_MAX_DAYS 90/' /etc/login.defs
sed -i 's/^PASS_MIN_DAYS.*/PASS_MIN_DAYS 7/' /etc/login.defs
# 2. 配置 PAM 密码复杂度
echo "password requisite pam_pwquality.so try_first_pass local_users_only retry=3 minlen=14 dcredit=-1 ucredit=-1 lcredit=-1 ocredit=-1" >> /etc/pam.d/system-auth
# 3. 配置账号锁定策略(/etc/pam.d/system-auth 中添加)
echo "auth required pam_faillock.so preauth audit silent deny=5 unlock_time=1800" >> /etc/pam.d/system-auth
echo "auth [default=die] pam_faillock.so authfail audit deny=5 unlock_time=1800" >> /etc/pam.d/system-auth
结果验证:使用弱密码 password123 测试,系统拒绝并提示复杂度不足;连续输错 5 次密码后,账号被锁定 30 分钟,pam_faillock 记录于 /var/log/faillock。
4.2.4 常见误区与总结
- 误区一:仅修改
/etc/login.defs而不重启服务。实际上该文件在用户下次登录时自动生效,无需重启。 - 误区二:忽略
chage -d 0的强制改密效果。该命令将“最后一次修改时间”设为 0,系统判定密码已过期,强制用户下次登录修改。 - 误区三:PAM 配置顺序错误导致无法登录。修改 PAM 前务必备份原文件,并通过
pam_tally2或pam_faillock测试验证。
4.3 sudo 机制:精细化提权管理
4.3.1 核心原理:从 su 到 sudo 的演进
su 命令需要目标用户密码,且切换后拥有完全权限,难以审计;sudo 则基于 /etc/sudoers 策略,允许授权用户以特定身份执行特定命令,并记录日志。sudo 的核心优势在于:最小权限分配(只授予必要命令)、可审计性(所有执行记录在案)、无需共享 root 密码。
4.3.2 操作流程:配置 sudo 策略
# 1. 使用 visudo 编辑(语法检查)
visudo
# 2. 配置示例
# 允许 alice 以 root 身份执行所有命令
alice ALL=(ALL) ALL
# 允许 devops 组执行系统管理命令,无需密码
%devops ALL=(ALL) NOPASSWD: /usr/bin/systemctl, /usr/bin/yum
# 允许 bob 仅能重启 Apache
bob ALL=(root) /usr/bin/systemctl restart httpd
# 3. 验证配置
sudo -l -U alice
| 配置项 | 含义 | 示例 |
|---|---|---|
| 用户/组 | 授权对象,组前加 % | %wheel 表示 wheel 组 |
| 主机列表 | 允许执行的主机 | ALL 表示所有主机 |
| 身份切换 | 以哪个用户身份执行 | (ALL) 可切换为任何用户 |
| 命令列表 | 允许执行的命令路径 | /usr/bin/systemctl |
| 标签 | NOPASSWD、NOEXEC 等 | NOPASSWD: 免密执行 |
4.3.3 案例拆解:运维人员 sudo 权限分级
场景:某互联网公司运维团队分为初级、高级、DBA 三个角色,需要分别授予不同级别的 sudo 权限。
# 定义命令别名
Cmnd_Alias SERVICE_CMDS = /usr/bin/systemctl, /usr/sbin/service
Cmnd_Alias PKG_CMDS = /usr/bin/yum, /usr/bin/dnf
Cmnd_Alias DB_CMDS = /usr/bin/mysql, /usr/bin/mysqldump
# 初级运维:只能查看服务状态和日志
junior_ops ALL=(ALL) /usr/bin/systemctl status *, /usr/bin/tail /var/log/messages
# 高级运维:管理服务、安装软件包
%senior_ops ALL=(ALL) SERVICE_CMDS, PKG_CMDS
# DBA:数据库操作,禁止其他 root 权限
dba_team ALL=(root) DB_CMDS, /usr/bin/mysqladmin
复盘:通过命令别名提高可读性;使用通配符 * 时需注意安全风险(如 systemctl status * 可能被利用读取敏感文件),建议使用 sudoedit 或精确命令路径。所有 sudo 操作记录在 /var/log/secure,定期审计可发现异常提权行为。
4.3.4 常见误区与总结
- 误区一:直接编辑
/etc/sudoers而非使用visudo。语法错误可能导致 sudo 完全失效,visudo提供语法检查。 - 误区二:授予
ALL=(ALL) ALL给普通用户。这等同于赋予 root 权限,违背最小权限原则。 - 误区三:忽略 sudo 日志审计。应定期检查
/var/log/secure中的 sudo 记录,发现异常命令执行及时响应。
4.4 ACL 访问控制列表:超越传统权限的精细控制
4.4.1 核心原理:ACL 的扩展能力
传统权限仅支持“属主、属组、其他”三类,无法满足“多个特定用户或组对同一文件有不同权限”的需求。ACL(Access Control List)在传统权限之上扩展了访问控制条目,允许为任意用户或组单独设置权限。ACL 通过 setfacl 和 getfacl 管理,其底层在文件扩展属性中存储 ACL 条目。
4.4.2 操作流程:ACL 的配置与验证
# 1. 为文件添加用户 ACL
setfacl -m u:alice:rwx /data/project
# 2. 为文件添加组 ACL
setfacl -m g:devteam:r-x /data/project
# 3. 设置默认 ACL(目录继承)
setfacl -m d:u:alice:rwx /data/project
# 4. 查看 ACL
getfacl /data/project
# 5. 移除 ACL
setfacl -x u:alice /data/project
setfacl -m m::rx 可调整 mask。
4.4.3 案例拆解:共享目录的协作权限设计
背景:研发部门需要共享 /srv/project 目录,要求:项目经理拥有完全控制权;开发人员可读写但不可删除他人文件;测试人员只读;外部顾问仅可访问 docs 子目录。
# 1. 创建目录结构
mkdir -p /srv/project/{src,docs,releases}
# 2. 设置传统权限(属主 root,属组 devteam)
chown root:devteam /srv/project
chmod 770 /srv/project
# 3. 设置 ACL
setfacl -m u:pm:rwx /srv/project
setfacl -m g:devteam:rwx /srv/project
setfacl -m g:testers:r-x /srv/project
setfacl -m u:consultant:r-x /srv/project/docs
# 4. 设置默认 ACL 确保新文件继承
setfacl -m d:u:pm:rwx /srv/project
setfacl -m d:g:devteam:rwx /srv/project
setfacl -m d:g:testers:r-x /srv/project
# 5. 验证
getfacl /srv/project
复盘:ACL 解决了传统权限无法实现的“多用户不同权限”问题。但需注意:ACL 会增加文件系统开销,且 NFS 等网络文件系统需开启 ACL 支持。此外,tar 备份时需使用 --acls 选项保留 ACL 信息。
4.4.4 常见误区与总结
- 误区一:认为 ACL 可以完全替代传统权限。实际上 ACL 是传统权限的补充,两者协同工作。
- 误区二:忽略 mask 的影响。当使用
chmod修改文件权限时,可能会意外改变 mask 值,导致 ACL 权限“失效”。 - 误区三:在根文件系统未开启 ACL 支持时使用。现代 Linux 默认支持,但挂载时可加
acl选项确保。
4.5 特殊权限:SUID、SGID 与 Sticky Bit
4.5.1 核心原理:特殊权限的语义
| 特殊权限 | 数值表示 | 符号表示 | 作用对象 | 核心效果 |
|---|---|---|---|---|
| SUID | 4 | u+s | 可执行文件 | 执行者临时获得文件属主的权限 |
| SGID | 2 | g+s | 可执行文件/目录 | 文件:执行者获得属组权限;目录:新文件继承属组 |
| Sticky Bit | 1 | o+t | 目录 | 仅文件属主、目录属主或 root 可删除文件 |
4.5.2 操作流程:设置与验证特殊权限
# 设置 SUID(例如 /usr/bin/passwd)
chmod u+s /usr/bin/myapp
chmod 4755 /usr/bin/myapp
# 设置 SGID(目录继承组)
chmod g+s /srv/shared
chmod 2770 /srv/shared
# 设置 Sticky Bit(例如 /tmp)
chmod o+t /tmp
chmod 1777 /tmp
# 验证
ls -l /usr/bin/myapp # 显示 -rwsr-xr-x
ls -ld /srv/shared # 显示 drwxrws---
ls -ld /tmp # 显示 drwxrwxrwt
4.5.3 案例拆解:SGID 实现团队目录自动继承
场景:开发团队需要共享 /srv/dev 目录,所有新创建的文件必须自动属于 devteam 组,且组内成员可互相编辑。
# 1. 创建目录并设置 SGID
mkdir /srv/dev
chown root:devteam /srv/dev
chmod 2770 /srv/dev
# 2. 验证 SGID 效果
touch /srv/dev/testfile
ls -l /srv/dev/testfile # 显示 -rw-r--r-- 1 root devteam
# 3. 结合 ACL 实现更细粒度控制
setfacl -m d:g:devteam:rwx /srv/dev
复盘:SGID 目录确保新文件自动继承属组,避免了每次创建后手动 chgrp 的繁琐操作。但需注意:SGID 对脚本文件无效(脚本执行时 SUID/SGID 位被忽略),仅对二进制可执行文件有效。
4.5.4 常见误区与总结
- 误区一:对 shell 脚本设置 SUID。Linux 内核出于安全考虑,会忽略脚本文件的 SUID/SGID 位。
- 误区二:在目录上设置 SUID。SUID 对目录无意义,应使用 SGID 实现组继承。
- 误区三:忽视 Sticky Bit 的适用范围。Sticky Bit 仅对目录有效,对文件设置无实际作用。
find / -perm -4000 -type f 扫描系统中的 SUID 文件,确认每个 SUID 文件的必要性。对于不再需要的 SUID 权限,及时使用 chmod u-s 移除。
4.6 综合实战:企业权限管理方案设计
背景:某金融科技公司新上线一个交易系统,服务器为 CentOS 9,需要设计一套完整的用户与权限管理方案,满足以下需求:开发人员可部署代码但不可修改配置;运维人员可管理服务但不能查看交易数据;审计人员只读所有日志;外包人员仅可访问测试环境。
方案设计:
- 用户与组规划:创建
developers、ops、auditors、vendors四个组,对应不同角色。 - 目录权限设计:
/srv/app:属主 root,属组 developers,权限 2750(SGID),开发人员可读写执行。/srv/app/config:属主 root,属组 ops,权限 750,仅运维可修改。/srv/logs:属主 root,属组 auditors,权限 750,审计人员可读。/srv/test:属主 root,属组 vendors,权限 1770(Sticky),外包人员可写但不可删除他人文件。
- sudo 策略:运维组可执行 systemctl 和日志查看命令;开发组仅可执行
git部署命令;审计组无 sudo 权限。 - 密码策略:所有用户 90 天改密,复杂度四级,连续失败 5 次锁定 30 分钟。
- ACL 补充:允许特定审计员读取交易日志目录,但不授予整个 logs 目录权限。
实施步骤:
# 创建组和用户
groupadd developers && groupadd ops && groupadd auditors && groupadd vendors
useradd -G developers -s /bin/bash dev1
useradd -G ops -s /bin/bash op1
useradd -G auditors -s /bin/bash audit1
useradd -G vendors -s /bin/bash vendor1
# 设置目录权限
mkdir -p /srv/{app,logs,test}
chown root:developers /srv/app && chmod 2750 /srv/app
chown root:ops /srv/app/config && chmod 750 /srv/app/config
chown root:auditors /srv/logs && chmod 750 /srv/logs
chown root:vendors /srv/test && chmod 1770 /srv/test
# 配置 sudo
echo "%ops ALL=(ALL) /usr/bin/systemctl, /usr/bin/tail" >> /etc/sudoers.d/ops
echo "%developers ALL=(ALL) /usr/bin/git" >> /etc/sudoers.d/dev
# 设置 ACL
setfacl -m u:audit1:r-x /srv/logs/trading
# 密码策略
chage -M 90 -m 7 -W 14 dev1
复盘与风险:该方案