Files
Cloud-book/Linux基础/用户权限管理.md
2025-08-27 17:10:05 +08:00

648 lines
22 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Linux系统是一个多用户多任务的分时操作系统任何一个要使用系统资源的用户都必须首先向系统管理员申请一个账号然后以这个账号的身份进入系统。
为了更加方便的管理多个用户,就出现了用户组的概念,关于用户和用户组:
* 系统上的每个进程(运行的程序)都是作为特定用户运行
* 每个文件是由一个特定的用户拥有
* 访问文件和目录受到用户的限制
* 与正在运行的进程相关联的用户确定该进程可访问的文件和目录
实现用户账号的管理,要完成的工作主要有如下几个方面:
* 用户账号的添加、删除与修改
* 用户口令的管理
* 用户组的管理
# 用户和用户组查看
## id
用于显示用户的ID以及所属群组的 ID
id会显示用户以及所属群组的实际与有效 ID。若两个 ID 相同,则仅显示实际 ID。若仅指定用户名称则显示目前用户的 ID。
```shell
id [OPTION]... [USER]
```
| 选项 | 含义 |
| :--- | :--- |
| `-g` | 显示用户所属群组的 ID |
| `-G` | 显示用户所属附加群组的 ID |
| `-n` | 显示用户,所属群组或附加群组的名称 |
| `-r` | 显示用户真实 ID用户真实的 uid |
| `-u` | 显示用户有效 ID可以都某些高权限用户通过有效 id 限制权限 |
### uid 约定
Linux 操作系统会依据用户的 uid 数值来判定这个用户的角色,分别如下
- **0**超级管理员也就是root在linux系统中拥有所有权力
- **1~999**:系统用户,系统用户往往是用来约束系统中的服务的
- **1000+**普通用户可以用来登陆和使用Linux操作系统
关于root用户
- uid是0
- 拥有操作系统所有权力
- 该用户有权力覆盖文件系统上的普通权限
- 安装或删除软件并管理系统文件和目录
- 大多数设备只能由root控制
### 案例演示
查看当前登陆的用户信息
```shell
[root@localhost ~]# id
uid=0(root) gid=0(root) =0(root) 环境=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
```
查看文件的拥有者
```shell
[root@localhost ~]# ll anaconda-ks.cfg 
-rw-------. 1 root root 1241 4月   4 16:53 anaconda-ks.cfg
```
![img](用户权限管理/文件属性介绍.png)
查看运行进程的用户名ps命令会在后面进程管理部分讲解
```shell
[root@localhost ~]# ps aux
USER PID %CPU %MEM    VSZ   RSS TTY STAT START   TIME COMMAND
root 2  0.0  0.0      0     0 ? S    09:06   0:00 [kthreadd]
root 3  0.0  0.0      0     0 ? S    09:06   0:01 [ksoftirqd/0]
root 4  0.1  0.0      0     0 ? R    09:06   0:09 [kworker/0:0]
root 5  0.0  0.0      0     0 ? S<   09:06   0:00 [kworker/0:0H]
```
## 相关的文件
之前说过 Linux 一切皆文件,所以用户和用户组相关的信息也都是保存在文本文件中的,下面列举出相关的文件。
### passwd 文件
用于保存用户的信息,一般第一行是 root 用户,下面都是其他用户
```shell
[root@localhost ~]# head -n 1 /etc/passwd
root:x:0:0:root:/root:/bin/bash
# 这个格式为用户名:密码:uid:gid:描述:家目录:登陆后执行的命令
```
### shadow 文件
格式中密码占位置太长了所以使用x来替代Linux系统会到shadow中查找x部分的的密码内容
```shell
[root@localhost ~]# head -n 1 /etc/shadow
root:$6$frokclXSnQa8EbKs$pWElbjPlmxjYh30tr8qLsTQVOhuPg7GmW9Sanm2yXAK8TNMgje1gyc/vwPgqvmSMf6VaoEvveM0gFvtETmXy/.::0:99999:7:::
# 这个格式为用户名:加密密码:最后一次修改时间:最小修改时间间隔:密码有效期:密码需要变更前的警告天数:密码过期后的宽限时间:账号失效时间:保留字段
```
格式不需要大家记住,只需要知道关于这个用户的密码和有效期都在这个文件中即可。
密码在`passwd`文件中会使用加密算法加密,所以别想知道我的密码是什么,加密算法默认是`$6`这个类型6的加密算法是sha-512。我们也可以在man手册中看到对shadow文件的详细解释。
```shell
[root@localhost ~]# man 5 shadow
# man手册一个有9个章节其中第5个章节是对文件格式的说明
# 对man手册感兴趣的同学也可以自己在网上查找学习man手册的更多内容
```
### group文件
用户和组的对应关系会保存在group文件中
```shell
[root@localhost ~]# head -n 1 /etc/group
root:x:0:
# 这个格式是组名:口令:组标识号:组内用户列表
```
# 用户组管理
## 添加用户组
groupadd 命令用于创建一个新的工作组,新工作组的信息将被添加到系统文件中
```shell
groupadd [选项]
```
### 常用选项
| 选项 | 含义 |
| :--- | :--- |
| `-g` | 指定新建工作组的 id |
| `-r` | 创建系统工作组系统工作组的组ID小于 500 |
| `-K` | 覆盖配置文件`/etc/login.defs` |
| `-o` | 允许添加组 ID 号不唯一的工作组 |
| `-f` | 如果指定的组已经存在,此选项将失明了仅以成功状态退出。当与 -g 一起使用并且指定的GID_MIN已经存在时选择另一个唯一的GID即-g关闭 |
### 案例演示
按照下图创建组并且指定gid并且检查是否成功
![img](用户权限管理/用户创建实战示例1.png)
```shell
[root@localhost ~]# groupadd hr -g 1000
[root@localhost ~]# groupadd sale -g 2000
[root@localhost ~]# groupadd it -g 3000
[root@localhost ~]# groupadd fd -g 4000
[root@localhost ~]# tail -n 4 /etc/group
hr:x:1000:
sale:x:2000:
it:x:3000:
fd:x:4000:
```
## 修改用户组
groupmod命令用于更改群组识别码或名称
```shell
groupmod [选项]
```
### 常用选项
- **-g**:将组 ID 改为 GID
- **-n**:改名为 NEW_GROUP
- **-o**:允许使用重复的 GID
### 案例演示
* 修改fd组的名字为finance
```shell
[root@localhost ~]# groupmod -n finance fd
[root@localhost ~]# tail -n 1 /etc/group
finance:x:4000:
```
## 删除用户组
groupdel命令用于删除群组
需要从系统上删除群组时可用groupdel(group delete)指令来完成这项工作。倘若该群组中仍包括某些用户,则必须先删除这些用户后,方能删除群组。
```shell
groupdel [组名]
```
### 案例演示
* 删除一个用户组
```shell
[root@localhost ~]# groupadd test
[root@localhost ~]# groupdel test
```
## 用户组成员管理
gpasswd 是 Linux 下工作组文件 /etc/group 和 /etc/gshadow 管理工具,用于将一个用户添加到组或者从组中删除
```shell
gpasswd [选项]
```
### 常用选项
- **-a**:添加用户到组;
- **-d**:从组删除用户;
- **-A**:指定管理员,可以执行添加或者删除组员;
- **-M**:替换组中的全部用户列表,不包含在内的用户将会从组中删除;
- **-R**限制用户登入组只有组中的成员才可以用newgrp加入该组。
### 案例演示
创建用户 itadmin并且将其加入 it 组
```shell
[root@localhost ~]# useradd itadmin
[root@localhost ~]# gpasswd -a itadmin it
正在将用户“itadmin”加入到“it”组中
[root@localhost ~]# cat /etc/group |grep it:
it:x:3000:itadmin
# 在组文件中,可以看到这个组的成员
[root@localhost ~]# id itadmin
uid=6667(itadmin) gid=6667(itadmin) =6667(itadmin),3000(it)
# 在用户的信息中,可以看到这个用户的所属组
```
# 用户管理
## 添加用户
useradd 可以用来添加新的用户账号
```shell
useradd [选项] 用户名
```
### 常用选项
* **-c comment**:指定一段注释性描述。
* **-d 目录**:指定用户主目录,如果此目录不存在,则同时使用-m选项可以创建主目录。
* **-m**:创建用户的主目录
* **-g 用户组**:指定用户所属的用户组,默认会创建一个和用户名同名的用户组。
* **-G 用户组**:用户组 指定用户所属的附加组,一个用户可以属于多个附加组。
* **-s Shell文件**指定用户的登录Shell。
* **-u 用户号**:指定用户的用户号,如果同时有-o选项则可以重复使用其他用户的标识号。
### 案例演示
* 添加一般用户
```shell
[root@localhost ~]# useradd user01
```
* 为添加的用户指定相应的用户组
```shell
[root@localhost ~]# useradd -g root user02
```
* 为新添加的用户指定home目录
```shell
[root@localhost ~]# useradd -d /home/test user03
```
* 建立一个不给登录的用户
```shell
[root@localhost ~]# useradd -s /sbin/nologin user04
```
- 查看用户描述信息
```bash
[root@localhost ~]# useradd -c "this is python_developmer user" python-developmer
[root@localhost ~]# cat /etc/passwd |grep python-developmer
python-developmer:x:1005:1005:this is python_developmer user:/home/python-developmer:/bin/bash
```
## 切换用户
su命令用户Linux系统中的用户切换
```BASH
su [选项] 用户名
```
### 常用选项
- `-`:以目标用户的环境变量启动新会话。这将模拟用户完全登录到新用户账户,包括其家目录、环境变量等。
- `-c 命令`:执行指定的命令,并在执行完毕后返回原始用户。
- `-s shell`:使用指定的 shell 替代目标用户的默认 shell。
## 修改用户usermod
usermod命令用于修改用户帐号
usermod可用来修改用户帐号的各项设定
```shell
usermod [选项] 登录
```
### 常用选项
- **-c<备注>**:修改用户帐号的备注文字。
- **-a**:追加,默认的修改是覆盖
- **-d登入目录>**:修改用户登入时的目录。
- **-e<有效期限>**:修改帐号的有效期限。
- **-f<缓冲天数>**:修改在密码过期后多少天即关闭该帐号。
- **-g<群组>**:修改用户所属的群组。
- **-G<群组>**:修改用户所属的附加群组。
- **-l<帐号名称>**:修改用户帐号名称。
- **-L**:锁定用户密码,使密码无效。
- **-s**修改用户登入后所使用的shell。
- **-u**修改用户ID。
- **-U**:解除密码锁定。
### 案例演示
* 更改登录的目录
```shell
[root@localhost ~]# usermod -d /home user01
[root@localhost ~]# su - user01
[user01@localhost ~]$ pwd
/home
```
* 改变用户的uid
```shell
[root@localhost ~]# usermod -u 6666 user02
```
## 删除用户userdel
userdel命令用于删除用户帐号
userdel可删除用户帐号与相关的文件。若不加参数则仅删除用户帐号而不删除相关文件
```shell
userdel [-r][用户帐号]
```
### 常用选项
- **-r**:删除用户登入目录以及目录中所有文件
### 案例演示
删除用户账号
```shell
[root@localhost ~]# userdel user04
```
删除用户账户和家目录
```shell
[root@localhost ~]# userdel -r user03
```
# passwd 文件中的 shell
查看`/etc/passwd`文件会发现在每行的最后是登录成功之后执行的命令,有两种是使用最为频繁的:
- /bin/bash这个是 Linux 的命令行工具,我们正常登陆之后默认就是进入命令行
- /sbin/nologin如果写成 nologin那么用户将无法登录有些用户是作为进程权限管理而存在的不需要登录。如果提供登录的功能反而不安全所以写成 nologin
```shell
[root@localhost ~]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
```
我们可以新建一个用户,然后尝试自定义登录成功之后执行的命令,用来加深印象。
```shell
[root@localhost ~]# useradd test01
[root@localhost ~]# tail -n 1 /etc/passwd
test01:x:1000:1000::/home/test01:/bin/vi
```
切换到test01用户会发现自动进入vi的界面说明最后的这个段内容就是用户登录之后会运行的程序
![img](用户权限管理/用户创建实战示例2.png)
# 用户密码管理
root用户可以直接设置普通用户密码普通用户必须要提供原密码才可以修改自己密码。
## passwd
passwd命令用来更改使用者的密码
```shell
passwd [选项...] <帐号名称>
```
### 常用选项
- **-k**:保持身份验证令牌不过期
- **-d**:删除已命名帐号的密码(只有根用户才能进行此操作)
- **-l**:锁定指名帐户的密码(仅限 root 用户)
- **-u**:解锁指名账户的密码(仅限 root 用户)
- **-x**:密码的最长有效时限(只有根用户才能进行此操作)
- **-n**:密码的最短有效时限(只有根用户才能进行此操作)
- **-w**:在密码过期前多少天开始提醒用户(只有根用户才能进行此操作)
- **-i**:当密码过期后经过多少天该帐号会被禁用(只有根用户才能进行此操作)
- **-S**:报告已命名帐号的密码状态(只有根用户才能进行此操作)
- **--stdin**:从标准输入读取令牌(只有根用户才能进行此操作)
### 案例演示
修改test01用户密码
```shell
[root@localhost ~]# passwd test01
更改用户 test01 的密码 。
新的 密码:
重新输入新的 密码:
passwd所有的身份验证令牌已经成功更新。
```
使用管道符设置用户密码
```shell
[root@localhost ~]# echo 123456 | passwd --stdin test01
更改用户 test01 的密码 。
passwd所有的身份验证令牌已经成功更新。
```
## login.defs文件
`/etc/login.defs`文件是用来创建用户时进行一定的限制,但是优先级低于`/etc/passwd``/etc/shadow`,如果有冲突的地方,系统会以`/etc/passwd``/etc/shadow`为准
下面是这个文件的内容egrep命令我们后续会讲到这边可以理解为不看文件的注释和空行。
```shell
[root@localhost ~]# egrep -v '^[ ]*$|^#' /etc/login.defs
MAIL_DIR /var/spool/mail # 系统消息(邮件)文件夹
PASS_MAX_DAYS 99999 # 密码有效最大天数 
PASS_MIN_DAYS 0 # 密码有效最小天数
PASS_MIN_LEN 5 # 密码长度
PASS_WARN_AGE 7 # 密码失效警告倒计时
UID_MIN                  1000 # 用户UID最小1000
UID_MAX                 60000 # 用户UID最大60000
SYS_UID_MIN               201 # 系统用户UID最小201
SYS_UID_MAX               999 # 系统用户UID最大999
GID_MIN                  1000 # 用户组GID最小1000
GID_MAX                 60000 # 用户组GID最大60000
SYS_GID_MIN               201
SYS_GID_MAX               999
CREATE_HOME yes # 创建家目录
UMASK           077 # 创建文件/目录的权限掩码
USERGROUPS_ENAB yes # 创建用户时同时生成组是  如果此处是no 创建的用户 会是gid=100(users)groups=100(users) 
ENCRYPT_METHOD SHA512 # 加密  方法  sha 512 这个方法生成的密码在/etc/shadow里面的第二列会以$6$开头
```
## chage
chage是用于更改用户密码过期信息
```shell
chage [选项] 登录
```
### 常用选项
- **-d**:设置密码的最后更改日期
- **-E 过期日期**:设置账号的过期日期
- **-I INACITVE**:设置密码过期后若未更改,多少天后用户账号被禁用。
- **-l**:显示用户账号的密码过期信息。
- **-m 最小天数**:设置两次改变密码之间相距的最小天数
- **-M 最大天数**:设置将两次改变密码之间相距的最大天数
- **-W 警告天数**:设置密码过期前的警告天数
### 案例演示
强制用户在下次登录的时候换密码
```shell
[root@localhost ~]# chage -d 0 test01
[root@localhost ~]# logout
You must change your password now and login again!
更改用户 test01 的密码 。
为 test01 更改 STRESS 密码。
当前UNIX 密码:
[root@localhost ~]# chage -l root
最近一次密码修改时间 :从不
密码过期时间 :从不
密码失效时间 :从不
帐户过期时间 :从不
两次改变密码之间相距的最小天数 0
两次改变密码之间相距的最大天数 99999
在密码过期之前警告的天数 7
# 设置用户 user01 的密码过期前7天提醒用户修改密码
[root@localhost ~]# chage -W 7 user01
# 设置用户 user01 的密码最短使用天数为7天即密码修改后7天内不能再次修改
[root@localhost ~]# chage -m 7 user01
[root@localhost ~]# chage -l user01
最近一次密码修改时间 11月 08, 2024
密码过期时间 :从不
密码失效时间 :从不
帐户过期时间 :从不
两次改变密码之间相距的最小天数 7
两次改变密码之间相距的最大天数 99999
在密码过期之前警告的天数 7
```
**小知识:** 当你新建用户的时候用户的home目录下会有一些默认的隐藏文件这些隐藏文件是在创建用户的时候从`/etc/skel/`中复制过去的。
# sudoers
Linux是多用户多任务的操作系统, 共享该系统的用户往往不只一个。出于安全性考虑, 有必要通过useradd创建一些非root用户, 只让它们拥有不完全的权限; 如有必要,再来提升权限执行。
sudo就是来解决这个需求的: 这些非root用户不需要知道root的密码就可以提权到root执行一些root才能执行的命令。
```shell
sudo [选项] [用户名] [命令]
```
## sudo 命令执行过程
1. 当用户执行sudo时系统会主动寻找`/etc/sudoers`文件判断该用户是否有执行sudo的权限
2. 确认用户具有可执行sudo的权限后让用户输入用户自己的密码确认
3. 若密码输入成功则开始执行sudo后续的命令
## 赋予用户 sudo 操作的权限
通过useradd添加的用户并不具备sudo权限。在ubuntu/centos/RockyLinux等系统下, 需要将用户加入admin组或者wheel组或者sudo组。以root用户身份执行如下命令, 将用户加入wheel/admin/sudo组。
```shell
usermod -a -G wheel <用户名>
```
如果提示wheel组不存在, 则还需要先创建该组
```shell
groupadd wheel
```
## 配置文件
sudo 的权限控制可以在 `/etc/sudoers` 文件中查看到。一般来说,通过 `cat /etc/sudoers` 指令来查看该文件, 会看到如下几行代码。
```shell
[root@localhost ~]# egrep -v '^[ ]*$|^#' /etc/sudoers
=====省略=====
root ALL=(ALL) ALL
%wheel ALL=(ALL) ALL
```
对/etc/sudoers文件进行编辑的代码公式可以概括为
```shell
授权用户/组 主机=[(切换到哪些用户或组)] [是否需要输入密码验证] 命令1,命令2,...
字段1 字段2 =[(字段3)] [字段4] 字段5
```
凡是[ ]中的内容, 都能省略; 命令和命令之间用`,`号分隔字段3、字段4是可以省略的。
* "字段1"不以%号开头的表示"将要授权的用户",以%号开头的表示"将要授权的组"。
* "字段2"表示允许登录的主机, ALL表示所有;如果该字段不为ALL,表示授权用户只能在某些机器上登录本服务器来执行sudo命令
* "字段3"如果省略, 相当于(root:root)表示可以通过sudo提权到root如果为(ALL)或者(ALL:ALL), 表示能够提权到(任意用户:任意用户组)。
* "字段4"的可能取值是NOPASSWD:。请注意NOPASSWD后面带有冒号:。表示执行sudo时可以不需要输入密码。
* 比如:`lucy ALL=(ALL) NOPASSWD: /bin/useradd`表示: 普通用户lucy可以在任何主机上, 通过sudo执行/bin/useradd命令, 并且不需要输入密码
* 比如:`peter ALL=(ALL) NOPASSWD: ALL`,表示: 普通用户peter可以在任何主机上, 通过sudo执行任何命令, 并且不需要输入密码。
* "字段5"是使用逗号分开一系列命令,这些命令就是授权给用户的操作; ALL表示允许所有操作。命令都是使用绝对路径, 这是为了避免目录下有同名命令被执行,从而造成安全隐患。
* 如果你将授权写成如下安全性欠妥的格式:`lucy ALL=(ALL) chown,chmod,useradd`那么用户就有可能创建一个他自己的程序, 也命名为userad, 然后放在它的本地路径中, 如此一来他就能够使用root来执行这个"名为useradd的程序"。这是相当危险的!
## 编辑配置文件
在实践中,去编辑`/etc/sudoers`文件,系统提示我没权限,这是因为`/etc/sudoers`的内容如此敏感,以至于该文件是只读的。所以,编辑该文件前,请确认清楚你知道自己正在做什么。
强烈建议通过`visudo`命令来修改该文件,通过`visudo`修改,如果配置出错,会有提示。
官方文档推荐的做法,不是直接修改`/etc/sudoers`文件,而是将修改写在`/etc/sudoers.d/`目录下的文件中。如果使用这种方式修改sudoers需要在`/etc/sudoers`文件的最后行,加上`#includedir /etc/sudoers.d`一行(默认已有)。需要注意,这个`#includedir /etc/sudoers.d`中的`#`并不是注释,请勿修改。
## sudo 选项
* **-u**:以指定用户或 ID 运行命令(或编辑文件)
* **-l**:显示出自己(执行 sudo 的使用者)的权限
* **-b**:将要执行的指令放在后台执行
* **-i**: 以目标用户身份运行一个登录 shell可同时指定一条命令。相当于切换到root不过只需要用户自己的密码即可。
## 案例演示
* 以管理员身份查看shadow文件
```shell
[root@localhost ~]# useradd user
[root@localhost ~]# echo 123456 | passwd --stdin user
[root@localhost ~]# usermod -a -G wheel user
[root@localhost ~]# su - user
[user@localhost ~]$ cat /etc/shadow
cat: /etc/shadow: 权限不够
[user@localhost ~]$ sudo -u root cat /etc/shadow
[sudo] user 的密码:
[user@localhost ~]$ sudo cat /etc/shadow
# sudo -u root用的比较多可以被精简为sudo
```
* 查看下列示例
```shell
papi ALL=(root) NOPASSWD: /bin/chown,/usr/sbin/useradd
```
* 表示: 用户papi能在所有可能出现的主机上, 提权到root下执行`/bin/chown`, 不必输入密码; 但运行`/usr/sbin/useradd`命令时需要密码
* 在具有sudo操作的用户下, 执行`sudo -l`可以查看到该用户被允许和被禁止运行的命令
* 查看下列示例
```shell
papi ALL=/usr/sbin/,/sbin/,!/usr/sbin/fdisk
```
* 命令前面加上!号表示取消该命令
* 用户papi在所有可能出现的主机上, 能够运行目录/usr/sbin和/sbin下所有的程序, 但fdisk除外。
* 默认情况下输入一次sudo可以保持15分钟不再要求输入密码如果想要延长这个时间可以修改配置文件
```shell
[root@localhost ~]# visudo
Defaults env_reset,pwfeedback,timestamp_timeout=60
# 这个是改成60分钟才会需要再次输入密码并且输入密码的时候会显示*号
```