跳转至

用户与权限管理

用户与权限管理

📌 学习时间: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:useraddadduser 的区别?

在 Debian/Ubuntu 中,adduser 是一个更友好的交互式脚本,会自动创建家目录、设置密码等。useradd 是底层命令,需要手动指定各项参数。在 CentOS 中两者是相同的。

Q3:如何安全地配置 sudo 权限?

遵循最小权限原则:只授予必要的命令权限。使用组管理而非个人。使用 visudo 编辑配置。避免 NOPASSWD: ALL。限制可执行的命令路径。启用日志审计。

Q4:什么是 PAM?它解决了什么问题?

PAM (Pluggable Authentication Modules) 是一个统一的认证框架。它解决了每个应用程序都需要自己实现认证逻辑的问题——通过模块化设计,应用只需调用 PAM 接口,具体的认证方式(密码、密钥、指纹等)由可插拔的模块实现。

Q5:如何查看用户最近的登录记录?

Bash
last alice              # 查看 alice 的登录历史
lastlog                 # 所有用户的最后登录
lastb                   # 登录失败记录
w                       # 当前登录用户
who                     # 当前登录用户(简洁)

🔧 练习题

基础练习

  1. 创建用户 testuser,家目录为 /home/testuser,Shell 为 bash
  2. 创建组 devteam,将 testuser 添加为组成员
  3. 配置 testuser 只能 sudo 执行 apt 和 systemctl 命令
  4. 为 testuser 设置密码有效期 90 天,提前 14 天警告

进阶练习

  1. 编写脚本批量创建 10 个用户,设置初始密码并要求首次登录修改
  2. 配置 PAM 实现 5 次登录失败后锁定 15 分钟
  3. 审计系统中所有 UID 为 0 的和无密码的用户

✅ 自我检查

  • 理解 UID/GID 和用户分类
  • 能解释 /etc/passwd 和 /etc/shadow 每个字段
  • 熟练使用 useradd/usermod/userdel
  • 能正确配置 sudo 权限
  • 了解 PAM 认证框架
  • 能配置密码策略

上一章03-文本处理三剑客 下一章05-进程管理