用户与权限管理¶
📌 学习时间:2-3天 📌 难度级别:⭐⭐ 基础 📌 前置知识:文件与目录管理
📚 章节概述¶
用户与权限管理是 Linux 系统管理的核心。本章全面讲解用户管理、组管理、sudo 权限配置、PAM 认证框架、/etc/passwd 和 /etc/shadow 详解以及密码策略配置,帮助你掌握多用户环境下的安全管理。
🎯 学习目标¶
- 掌握用户管理命令(useradd/usermod/userdel/passwd)
- 理解组管理机制(groupadd/groupmod/groupdel)
- 深入理解 /etc/passwd、/etc/shadow、/etc/group 文件
- 掌握 sudo 权限配置和安全实践
- 了解 PAM 认证框架
- 能配置合理的密码策略
📖 1. 用户与组概念¶
1.1 Linux 用户分类¶
Bash
# Linux 中每个用户有一个 UID(User ID)
# 用户分为三类:
# 1. root 用户(超级管理员)
# UID = 0
# 拥有系统全部权限
# 2. 系统用户(服务账户)
# UID = 1-999(CentOS/RHEL)或 1-999(Ubuntu)
# 用于运行系统服务,通常不能登录
# 如 www-data, mysql, nginx
# 3. 普通用户
# UID >= 1000
# 由管理员创建,有受限的权限
# 查看当前用户信息
whoami # 当前用户名
id # 详细的用户和组信息
# uid=1000(alice) gid=1000(alice) groups=1000(alice),27(sudo),1001(developers)
id -u # 仅 UID
id -g # 仅主组 GID
id -G # 所有组 GID
id -Gn # 所有组名
# 查看登录用户
who # 当前登录的用户
w # 更详细的登录信息(含负载)
last # 历史登录记录
lastlog # 所有用户最后登录时间
1.2 用户相关文件¶
/etc/passwd — 用户账户信息¶
Bash
# 格式:用户名:密码占位:UID:GID:描述信息:家目录:登录Shell
# 每个字段含义:
cat /etc/passwd
# root:x:0:0:root:/root:/bin/bash
# daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
# nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
# alice:x:1000:1000:Alice Smith,,,:/home/alice:/bin/bash
# mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/false
# 字段详解:
# alice - 用户名(登录名)
# x - 密码占位符(实际密码存在 /etc/shadow)
# 1000 - UID(用户ID)
# 1000 - GID(主组ID)
# Alice Smith,,, - GECOS 字段(描述信息,用逗号分隔:全名,办公室,电话等)
# /home/alice - 家目录
# /bin/bash - 登录 Shell
# 提取信息
grep alice /etc/passwd
awk -F: '$3 >= 1000 && $7 != "/usr/sbin/nologin" {print $1}' /etc/passwd
/etc/shadow — 密码信息(仅root可读)¶
Bash
# 格式:用户名:加密密码:最后修改时间:最小修改间隔:最大有效期:警告天数:不活动天数:过期日期:保留
sudo cat /etc/shadow
# alice:$6$rounds=5000$salt$hashedpassword:19738:0:99999:7:::
# 字段详解:
# alice - 用户名
# $6$rounds=5000$salt$hashed... - 加密密码
# $6$ = SHA-512 算法
# $5$ = SHA-256 算法
# $1$ = MD5 算法(已不安全)
# !! = 密码被锁定
# * = 不能通过密码登录
# 19738 - 最后修改日期(从1970.1.1起的天数)
# 0 - 最小修改间隔(0=可以随时修改)
# 99999 - 密码最大有效期(天)
# 7 - 密码过期前几天开始警告
# (空) - 密码过期后几天账户被禁用
# (空) - 账户过期日期
# (空) - 保留字段
# 查看密码策略
sudo chage -l alice
# Last password change : Jan 15, 2024
# Password expires : never
# Password inactive : never
# Account expires : never
# Minimum number of days between password change : 0
# Maximum number of days between password change : 99999
# Number of days of warning before password expires : 7
/etc/group — 组信息¶
Bash
# 格式:组名:密码:GID:组成员列表
cat /etc/group
# root:x:0:
# sudo:x:27:alice,bob
# developers:x:1001:alice,charlie
# www-data:x:33:
# 字段详解:
# developers - 组名
# x - 组密码占位(极少使用)
# 1001 - GID(组ID)
# alice,charlie - 组成员(逗号分隔)
# 查看用户所属的组
groups alice
# alice : alice sudo developers
📖 2. 用户管理¶
2.1 创建用户 — useradd¶
Bash
# 基本创建
sudo useradd bob # 创建用户(不创建家目录——CentOS默认)
sudo useradd -m bob # 创建用户和家目录(-m 推荐始终使用)
sudo useradd -m -s /bin/bash bob # 指定 Shell
# 完整创建选项
sudo useradd -m \
-d /home/bob \ # 指定家目录
-s /bin/bash \ # 指定 Shell
-g developers \ # 指定主组
-G sudo,docker \ # 指定附加组
-u 1500 \ # 指定 UID
-c "Bob Smith" \ # 备注(GECOS)
-e 2025-12-31 \ # 账户过期日期
bob
# 设置密码
sudo passwd bob # 交互式设置密码
echo "bob:password123" | sudo chpasswd # 批量设置密码(脚本使用)
# 创建系统用户(用于运行服务)
sudo useradd -r -s /usr/sbin/nologin -d /var/lib/myapp myapp
# useradd 默认配置
cat /etc/default/useradd
# GROUP=100
# HOME=/home
# INACTIVE=-1
# EXPIRE=
# SHELL=/bin/sh
# SKEL=/etc/skel # 家目录模板目录
# 查看 /etc/skel — 新用户家目录的模板
ls -la /etc/skel/
# .bash_logout
# .bashrc
# .profile
2.2 修改用户 — usermod¶
Bash
# 修改用户属性
sudo usermod -s /bin/zsh bob # 修改 Shell
sudo usermod -d /home/newbob -m bob # 修改家目录(-m 移动文件)
sudo usermod -g developers bob # 修改主组
sudo usermod -aG docker bob # 添加到附加组(-a 是追加,不加会覆盖!)
sudo usermod -c "Robert Smith" bob # 修改备注
sudo usermod -l robert bob # 修改用户名(bob → robert)
sudo usermod -u 2000 bob # 修改 UID
sudo usermod -e 2025-06-30 bob # 设置账户过期日期
# ⚠️ 重要:-aG vs -G
sudo usermod -G docker bob # 设置附加组为 docker(覆盖原有附加组!)
sudo usermod -aG docker bob # 向现有附加组追加 docker(安全操作)
# 锁定/解锁账户
sudo usermod -L bob # 锁定账户(密码前加!)
sudo usermod -U bob # 解锁账户
2.3 删除用户 — userdel¶
Bash
sudo userdel bob # 删除用户(保留家目录)
sudo userdel -r bob # 删除用户和家目录
sudo userdel -f bob # 强制删除(即使用户已登录)
# 删除前的最佳实践
# 1. 备份用户数据
sudo tar czf /backup/bob_home_$(date +%F).tar.gz /home/bob # $()命令替换:执行命令并获取输出
# 2. 查找用户的所有文件
find / -user bob 2>/dev/null
# 3. 删除用户
sudo userdel -r bob
# 4. 清理残留文件
find / -user 1001 2>/dev/null # 用UID查找(用户已删除,文件显示UID)
2.4 批量用户管理¶
Bash
#!/bin/bash
# 批量创建用户脚本
USER_FILE="users.txt"
# users.txt 格式:
# username:full_name:department
# alice:Alice Smith:Engineering
# bob:Bob Jones:Marketing
while IFS=: read -r username fullname dept; do
# 跳过空行和注释
[[ -z "$username" || "$username" =~ ^# ]] && continue
# 创建组(如果不存在)
getent group "$dept" &>/dev/null || sudo groupadd "$dept"
# 创建用户
if ! id "$username" &>/dev/null; then
sudo useradd -m -s /bin/bash -g "$dept" -c "$fullname" "$username"
# 设置初始密码(要求首次登录修改)
echo "${username}:Welcome123!" | sudo chpasswd
sudo chage -d 0 "$username" # 强制下次登录修改密码
echo "Created user: $username ($fullname) -> $dept"
else
echo "User exists: $username"
fi
done < "$USER_FILE"
📖 3. 组管理¶
3.1 组的概念¶
Bash
# 每个用户有:
# - 一个主组(primary group):创建文件时默认使用
# - 零个或多个附加组(supplementary groups):额外的权限
# 创建组
sudo groupadd developers
sudo groupadd -g 2000 testers # 指定 GID
# 修改组
sudo groupmod -n dev developers # 重命名 developers → dev
sudo groupmod -g 2001 dev # 修改 GID
# 删除组
sudo groupdel testers # 删除组(不能删除作为用户主组的组)
# 管理组成员
sudo gpasswd -a alice developers # 添加 alice 到 developers
sudo gpasswd -d alice developers # 从 developers 移除 alice
sudo gpasswd -M alice,bob,charlie developers # 设置组成员列表
# 查看组信息
getent group developers # 查看组信息
groups alice # 查看 alice 的所有组
id alice # 查看 alice 的详细信息
3.2 新建文件的组归属¶
Bash
# 新文件的组归属规则:
# 1. 如果目录未设置 SGID:新文件属于用户的主组
# 2. 如果目录设置了 SGID:新文件属于该目录的组
# 团队协作最佳实践
sudo mkdir /shared/project
sudo chgrp developers /shared/project
sudo chmod 2775 /shared/project # SGID + rwxrwxr-x
# 现在所有在此目录下创建的文件都属于 developers 组
📖 4. sudo 配置¶
4.1 sudo 基础¶
Bash
# sudo 允许普通用户以其他用户(通常是 root)的身份执行命令
sudo command # 以 root 执行
sudo -u bob command # 以 bob 用户执行
sudo -i # 切换到 root 的 Shell
sudo -s # 以 root 开一个 Shell(不改变环境)
sudo su - # 切换到 root(与 sudo -i 类似)
sudo -l # 查看当前用户的 sudo 权限
sudo -k # 清除 sudo 密码缓存
4.2 /etc/sudoers 配置¶
Bash
# ⚠️ 永远使用 visudo 编辑 sudoers,它会检查语法错误
sudo visudo
# sudoers 语法:
# 谁 在哪台机器上=(以谁的身份) 可以执行什么命令
# user host=(runas) command
# 示例配置
root ALL=(ALL:ALL) ALL
# root 在所有主机上,可以以任何用户和组的身份,执行任何命令
%sudo ALL=(ALL:ALL) ALL
# sudo 组的所有成员,同上
alice ALL=(ALL) NOPASSWD: ALL
# alice 执行 sudo 不需要密码(方便但有安全风险)
bob ALL=(ALL) /usr/bin/apt, /usr/bin/systemctl
# bob 只能 sudo 执行 apt 和 systemctl
charlie ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx
# charlie 可以无密码重启 nginx
# 使用 Cmnd_Alias 定义命令组
Cmnd_Alias NETWORK = /sbin/ifconfig, /sbin/route, /usr/bin/ip
Cmnd_Alias SERVICE = /usr/bin/systemctl start *, /usr/bin/systemctl stop *
%netadmin ALL=(ALL) NETWORK
%sysadmin ALL=(ALL) SERVICE
# 推荐:使用 /etc/sudoers.d/ 目录
# 为每个用户或团队创建独立文件
sudo visudo -f /etc/sudoers.d/alice
# alice ALL=(ALL) NOPASSWD: /usr/bin/docker
# 安全配置
Defaults requiretty # 必须通过终端使用 sudo
Defaults logfile="/var/log/sudo.log" # 记录 sudo 日志
Defaults passwd_tries=3 # 密码最多尝试3次
Defaults timestamp_timeout=5 # 缓存5分钟
4.3 sudo 安全最佳实践¶
Bash
# 1. 最小权限原则:只给用户需要的权限
# ❌ 不推荐
alice ALL=(ALL) NOPASSWD: ALL
# ✅ 推荐
alice ALL=(ALL) /usr/bin/systemctl restart nginx, /usr/bin/journalctl
# 2. 禁止 sudo su 和 sudo bash 的变通方法
alice ALL=(ALL) ALL, !/bin/su, !/bin/bash, !/bin/sh
# 3. 审计 sudo 使用
# 查看 sudo 日志
grep sudo /var/log/auth.log # Ubuntu
grep sudo /var/log/secure # CentOS
# 4. 不要直接编辑 /etc/sudoers,使用 visudo
# 5. 使用组而不是单个用户管理 sudo 权限
📖 5. PAM 认证框架¶
5.1 PAM 概述¶
Bash
# PAM(Pluggable Authentication Modules)— 可插拔认证模块
# 提供统一的认证接口,应用程序不需要知道具体的认证机制
# PAM 配置目录
ls /etc/pam.d/
# common-auth common-password common-session
# login sshd sudo
# su passwd
# PAM 四个管理组
# auth — 认证(验证用户身份)
# account — 账户管理(检查是否允许访问)
# password — 密码管理(修改密码时的规则)
# session — 会话管理(登录/注销时的操作)
5.2 PAM 配置文件格式¶
Bash
# 格式:类型 控制标志 模块路径 [参数]
cat /etc/pam.d/login
# auth required pam_securetty.so
# auth required pam_unix.so nullok
# account required pam_unix.so
# session required pam_unix.so
# 控制标志
# required — 必须成功,失败后继续检查其他模块,最终返回失败
# requisite — 必须成功,失败后立即返回
# sufficient — 成功则立即返回成功(不再检查后续模块),失败则忽略
# optional — 不影响认证结果,除非是唯一的模块
# 常用 PAM 模块
# pam_unix.so — 传统 Unix 密码认证
# pam_deny.so — 总是拒绝
# pam_permit.so — 总是允许
# pam_cracklib.so — 密码强度检查
# pam_pwquality.so — 密码质量检查(替代 cracklib)
# pam_limits.so — 资源限制(/etc/security/limits.conf)
# pam_faillock.so — 失败锁定
# pam_tally2.so — 登录失败计数
5.3 PAM 实践配置¶
Bash
# 配置登录失败锁定策略
# /etc/pam.d/common-auth (Ubuntu)
auth required pam_faillock.so preauth silent deny=5 unlock_time=900
auth required pam_unix.so
auth [default=die] pam_faillock.so authfail deny=5 unlock_time=900
# 效果:5次密码错误后锁定账户15分钟
# 查看锁定状态
sudo faillock --user alice
# 手动解锁
sudo faillock --user alice --reset
# 配置密码强度 (/etc/pam.d/common-password)
password requisite pam_pwquality.so retry=3 minlen=12 difok=3 \
ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1
# minlen=12 : 最小12字符
# difok=3 : 新密码与旧密码至少3个字符不同
# ucredit=-1 : 至少1个大写字母
# lcredit=-1 : 至少1个小写字母
# dcredit=-1 : 至少1个数字
# ocredit=-1 : 至少1个特殊字符
# 资源限制 /etc/security/limits.conf
# 格式:域 类型 项目 值
alice hard nofile 65535 # alice 最大文件描述符
@developers soft nproc 4096 # developers 组进程数
* hard core 0 # 禁止所有用户生成 core dump
📖 6. 密码策略¶
6.1 密码有效期管理¶
Bash
# chage — 修改密码策略
sudo chage -l alice # 查看密码策略
# 设置策略
sudo chage -M 90 alice # 密码最长有效期90天
sudo chage -m 7 alice # 密码最小修改间隔7天
sudo chage -W 14 alice # 过期前14天开始警告
sudo chage -I 30 alice # 过期后30天禁用账户
sudo chage -E 2025-12-31 alice # 账户过期日期
sudo chage -d 0 alice # 强制下次登录修改密码
# 全局密码策略 /etc/login.defs
cat /etc/login.defs | grep -v '^#' | grep -v '^$' # grep文本搜索:按模式匹配行
# PASS_MAX_DAYS 90 # 密码最长有效期
# PASS_MIN_DAYS 7 # 密码最小修改间隔
# PASS_MIN_LEN 12 # 密码最小长度
# PASS_WARN_AGE 14 # 过期前警告天数
# UID_MIN 1000 # 普通用户最小 UID
# UID_MAX 60000 # 普通用户最大 UID
# CREATE_HOME yes # 创建用户时自动创建家目录
# ENCRYPT_METHOD SHA512 # 密码加密算法
6.2 密码安全最佳实践¶
Bash
# 1. 强密码策略
# 配置 /etc/pam.d/common-password
password requisite pam_pwquality.so \
minlen=12 minclass=3 maxrepeat=3 maxsequence=3 \
reject_username enforce_for_root
# 2. 禁用不使用的账户
sudo usermod -L olduser # 锁定
sudo chage -E 0 olduser # 立即过期
# 3. 定期审计
# 查找无密码的账户
sudo awk -F: '($2 == "" || $2 == "!") {print $1}' /etc/shadow # &&前一个成功才执行后一个;||前一个失败才执行
# 查找 UID 为 0 的用户(应该只有 root)
awk -F: '$3 == 0 {print $1}' /etc/passwd # awk文本处理:按列提取和格式化数据
# 查找密码永不过期的用户
sudo awk -F: '$5 == 99999 || $5 == "" {print $1}' /etc/shadow
# 4. 检查可登录的用户
grep -v '/nologin\|/false' /etc/passwd | cut -d: -f1 # |管道:将前一命令的输出作为后一命令的输入
📖 7. su 与用户切换¶
Bash
# su — 切换用户
su bob # 切换到 bob(不切换环境)
su - bob # 切换到 bob(切换完整环境,推荐)
su - # 切换到 root
# su 和 sudo su 的区别
su - root # 需要 root 密码
sudo su - # 需要当前用户密码
# 以其他用户执行命令
su - bob -c "whoami" # 以 bob 身份执行命令
sudo -u www-data whoami # 以 www-data 身份执行
# 限制 su 的使用
# 只允许 wheel 组的用户使用 su
# /etc/pam.d/su
auth required pam_wheel.so # 取消此行注释
sudo usermod -aG wheel alice # 将 alice 添加到 wheel 组
📖 8. 面试要点¶
高频面试题¶
Q1:/etc/passwd 和 /etc/shadow 的区别?
/etc/passwd存储用户基本信息(用户名、UID、GID、家目录、Shell),所有用户可读。/etc/shadow存储加密密码和密码策略,只有 root 可读。分离设计是为了安全——即使 passwd 被读取,密码也不会泄露。
Q2:useradd 和 adduser 的区别?
在 Debian/Ubuntu 中,
adduser是一个更友好的交互式脚本,会自动创建家目录、设置密码等。useradd是底层命令,需要手动指定各项参数。在 CentOS 中两者是相同的。
Q3:如何安全地配置 sudo 权限?
遵循最小权限原则:只授予必要的命令权限。使用组管理而非个人。使用 visudo 编辑配置。避免
NOPASSWD: ALL。限制可执行的命令路径。启用日志审计。
Q4:什么是 PAM?它解决了什么问题?
PAM (Pluggable Authentication Modules) 是一个统一的认证框架。它解决了每个应用程序都需要自己实现认证逻辑的问题——通过模块化设计,应用只需调用 PAM 接口,具体的认证方式(密码、密钥、指纹等)由可插拔的模块实现。
Q5:如何查看用户最近的登录记录?
🔧 练习题¶
基础练习¶
- 创建用户 testuser,家目录为 /home/testuser,Shell 为 bash
- 创建组 devteam,将 testuser 添加为组成员
- 配置 testuser 只能 sudo 执行 apt 和 systemctl 命令
- 为 testuser 设置密码有效期 90 天,提前 14 天警告
进阶练习¶
- 编写脚本批量创建 10 个用户,设置初始密码并要求首次登录修改
- 配置 PAM 实现 5 次登录失败后锁定 15 分钟
- 审计系统中所有 UID 为 0 的和无密码的用户
✅ 自我检查¶
- 理解 UID/GID 和用户分类
- 能解释 /etc/passwd 和 /etc/shadow 每个字段
- 熟练使用 useradd/usermod/userdel
- 能正确配置 sudo 权限
- 了解 PAM 认证框架
- 能配置密码策略
上一章:03-文本处理三剑客 下一章:05-进程管理