基本概念
Linux的用户和组的作用主要有两点:
- 登录操作系统使用资源。
- 以某个用户和组的身份运行服务。
用户和组的概念的理解,需要与Linux的文件权限共同来理解。例如
- 某个内存中的进程对于某个系统资源是否有权限,要根据运行该进程的用户和组对于该资源是否有权限来决定。
- 用户创建了某个文件后,该文件的所有者与所有组的归属取决于创建文件的用户和组。
- 某个用户想要读取、修改、删除、执行某个文件,取决于该用户及其基本组对应文件的权限关系。
- 等等其他的情况。
用户
用户有用户名、UID、基本组、附加组等主要信息。UID由16位二进制表示,因此取值范围是0~65535。
分类
- 管理员:用户名为root,UID为0。
- 普通用户:
- 系统用户:UID范围为201~499(CentOS 6)或者201~999(CentOS 7)。
- 登录用户:UID范围为500~60000(CentOS 6)或者1000~60000(CentOS 7)。
组
分类1
- 管理员组:组名为root,GID为0。
- 普通用户组:
- 系统组:GID范围为201~499(CentOS 6)或者201~999(CentOS 7)。
- 登录组:GID范围为500~60000(CentOS 6)或者1000~60000(CentOS 7)。
分类2
- 用户的基本组:默认情况下,在创建用户的时候会创建一个和用户名相同的组,该组即为用户的基本组。用户在创建文件的时候,文件的所有组是用户的基本组而非附加组。
- 用户的附加组:一般是单独额外创建的分组,比如开发分组dev,然后将多个用户纳入此组。
分类3
- 私有组:组中只有一个用户,一般基本组是私有组。
- 公共组:组中含有多个用户,一般附加组是私有组。
相关的文件
程序包主配置文件:/etc/login.defs
我们在Linux系统当中,维护管理用户和组,都是使用程序包shadow-utils当中的命令(useradd和groupadd等)来实现的。
其中,/etc/login.defs就是这些命令调用的主配置文件,用于定义默认值。该文件中具体的每个参数的含义可以参考man手册login.defs(5)。
该配置文件的参数定义的是包shadow-utils中的命令的行为。因此像passwd命令这种使用PAM机制的命令,它们的默认行为,要在其他地方进行配置。
该配置文件中,会影响PAM模块的参数有这些:
- ENCRYPT_METHOD和SHA_CRYPT_MAX_ROUNDS影响pam_unix。
- FAIL_DELAY影响pam_faildelay。
- UMASK影响pam_umask。
具体请参考pam(8)。
接下来我们来看一下默认情况下配置文件中的配置。
# 这个参数应该是必须的。
# 定义用户的邮箱目录。也可以是一个相对于家目录的文件名。
# 如果两者都定义了,则取优先定义的那个。
# QMAIL_DIR是用于Qmail的。
#
#QMAIL_DIR Maildir
MAIL_DIR /var/spool/mail
#MAIL_FILE .mail
# 定义密码的生命周期。
#
PASS_MAX_DAYS 99999
PASS_MIN_DAYS 0
PASS_MIN_LEN 5
PASS_WARN_AGE 7
# 定义普通用户和系统用户的UID取值范围。
#
UID_MIN 1000
UID_MAX 60000
SYS_UID_MIN 201
SYS_UID_MAX 999
# 定义普通用户组和系统用户组的GID取值范围。
#
GID_MIN 1000
GID_MAX 60000
SYS_GID_MIN 201
SYS_GID_MAX 999
# 定义一个脚本,用于在删除用户的时候顺带执行的脚本,脚本一般用于删除用户所创建的at/cron/print相关作业等。
#
#USERDEL_CMD /usr/sbin/userdel_local
# 定义是否在创建用户的时候要为其创建家目录。该选项会被useradd的-m选项所覆盖。
#
CREATE_HOME yes
# 定义权限的掩码,若未定义,则为022。
#
UMASK 077
# 定义是否允许userdel删除没有成员的用户组。
#
USERGROUPS_ENAB yes
# 定义所使用的加密算法。
ENCRYPT_METHOD SHA512
关于shadow-utils中的命令与login.defs配置文件的参数的对照关系,请查看login.defs(5)中的CROSS REFERENCES段落。
骨架目录:/etc/skel/
骨架(skeleton)目录是当新建用户的时候,如果创建了家目录,那么就将骨架目录中的内容复制到用户家目录中,类似一个模板。默认的骨架目录是/etc/skel/,可通过useradd命令更改。
用户信息文件:/etc/passwd
该文件存储了用户的信息,详细的关于该文件的描述,可以查看此man手册。
[root@C7 ~]# man 5 passwd
由于该文件是记录所有的用户的登录账户信息的,因此它必须对所有人具备读取的权限,但是仅能对管理员具备写权限。一些程序,例如ls命令,使用此文件来实现UID至用户名的映射。
-rw-r--r--. 1 root root 2243 Sep 27 15:59 /etc/passwd
该文件中每一行即为一个用户的信息,每行的格式如下。
account:password:UID:GID:GECOS:directory:shell
- account:用户名。
- password:曾经存储用户加密后的密码,后来由于硬件解密该密码的速度太慢了,就采取了影子密码组件(shadow password suite)来取代了该方法;从此,此字段就仅使用一个x当做占位符来表示了,真实的加密后的密码存储于/etc/shadow文件中。
- UID:用户的ID。
- GID:用户的基本组的ID。
- GECOS:全程叫做“General Electric Comprehensive Operating System”,不过我们理解为注释信息即可;它可以被finger命令所使用。
- directory:用户的家目录。
- shell:登录时默认运行的shell;该值会被当做环境变量SHELL的值;可选的shell存放于/etc/shells。
示例
root:x:0:0:root:/root:/bin/bash
libstoragemgmt:x:997:994:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin
zwl:x:1000:1000:zhangwenlong:/home/zwl:/bin/bash
shell文件:/etc/shells
表示用户登录时可选择的shell。
其中/sbin/nologin是比较特殊的shell,如果某个用户的shell为此shell,那么该用户便无法登录系统了。
[root@C7 ~]# cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh
用户密码文件:/etc/shadow
该文件存储了用户的密码以及用户账户的生命周期,详细的关于该文件的描述,可以查看此man手册。
[root@C7 ~]# man 5 shadow
该文件中每一行即为一个用户的信息,每行的格式如下。
login name:encrypted password:date of last password change:minimum password age:maximum password age:password warning period:password inactivity period:account expiration date:reserved field
- login name:用户名。
- encrypted password:加密后的密码;这个字段的具体解释需要参考crypt(3)的man手册。
- 字段的值:
- 密码为空,表示用户的密码被删除了,可通过“passwd -d”来删除。
- $6$RQ/mlpy9$fvFU...ROh1:如果是这样的格式(下文有详述格式),表示用户有密码。其中“...”表示省略。
- 如果该字段包含了!或者*的话,那么密码就失效了,用户就无法通过密码登录系统了。用户刚创建的时候,该字段的值为“!!”。
- 如果该字段是以一个!开头的话,表示密码被锁了。!剩余的部分,就是用户的加密的密码了。在CentOS 6和7上测试的时候,锁用户密码都是以两个!开头。
- 加密后的密码也有自己的格式。“$id$salt$encrypted”
- id:加密算法。
- 1:MD5算法。
- 2a:Blowfish算法。
- 5:SHA-256。
- 6:SHA-512。
- salt:一个随机数,创建密码的时候由系统随机生成,创建好密码之后该随机数被固定存储在shadow文件中用于用户密码登录验证。salt的存在使得即便2个用户使用相同的密码,加密后的密码也是不同的。
- encrypted:加密后的密码;是通过加密算法+salt+用户键入的密码计算得出的。
- id:加密算法。
- 字段的值:
- date of last password change:上次修改密码的日期,值为一个整型数字,表示从Unix纪元(1970年1月1日)开始经过的天数。值为0表示用户下次登录时必须修改自己的密码,修改密码要求输入自己的密码,如果输错或者不愿意修改密码,会无法登录。值为空表示密码的生命周期特性被禁用;生命周期特性就是后面几个字段的含义。
- minimum password age:设置密码最短生命周期。表示在上次密码修改之后,用户必须等待多少天才可以再次修改密码。值为空或者为0表示没有该限制。
- maximum password age:设置密码最长生命周期。表示在上次密码修改之后,经过多少天,用户必须修改密码,否则密码过期。密码过期并不表示用户就无法使用密码登录系统了!具体要看密码失效周期的设置!这些天数过后,密码可能还有效,用户在下次登录系统时会被要求修改密码。值为空表示该字段以及后续的password warning period和password inactivity period字段都失效。如果这个值小于minimum password age,那么用户无法修改自己的密码。
- password warning period:设置密码警告周期。在密码过期之前(详见maximum password age)的多少天时间内,用户会收到警告。值为空或者为0表示没有警告。
- password inactivity period:设置密码失效周期。在密码过期之后(详见maximum password age)的一段时间内,过期的密码是仍然有效的。但是过了密码失效周期以后,用户就无法使用过期的密码登录系统了,到那时只能联系管理员。值为空表示用户可以一直使用过期的密码。
- account expiration date:账户过期的日期,值为一个整型数字,表示从Unix纪元(1970年1月1日)开始经过的天数。注意,账户过期有别于密码过期;密码过期表示用户不能以密码形式登录系统,但可以以其他形式(例如密钥)登录系统,而账户过期的话,用户无论以什么方式都无法登录系统。值为空表示账户永远不会过期。值不可以被设置为0,否则会引起系统混乱。这个值是一个比较绝对的值,到期后账户直接过期,不像密码过期那样有警告和缓冲期。
- reserved field:保留字段,用于将来使用,目前是为空的状态。
图示:
示例:
root:$6$uqrbcQj0HJcu4s/Q$7qnd9vk27VsiXMW1xzzxSxueRNaJLa/nCBw0j.d7SSs4bfT.7rfD806FlKV6Gu85zvyHs035AGMCJ5N77Hr7V0::0:99999:7:::
libstoragemgmt:!!:17801::::::
zwl:$6$anzpwvElddU2SXGz$7rCAP4sFaKBV5k8PyWg0wmvbdD38aLgdQLjFdPlAbddIcyY71FWsxm3XQ61w28iq5lR7XPntzXRzWqxKTvGfG1::0:99999:7:::
组信息文件:/etc/group
包含了组的信息,每行表示一个组。
格式如下。
group_name:password:GID:user_list
- password:组密码。一般是使用x作为占位符,加密后的密码记录在/etc/gshadow文件中。为空表示没有组密码。
- user_list:以逗号分隔的用户列表字段,表示以本组作为附加组的用户。
组密码文件:/etc/gshadow
包含组的影子信息,每行表示一个组。该文件对普通用户不可以具备读权限。
----------. 1 root root 774 Sep 27 15:59 /etc/gshadow
格式如下:
group name:encrypted password:administrators:members
- encrypted password:格式和/etc/shadow中用户的密码字段是一致的,含义详见crypt(3);组密码的作用是使得非本组成员想要拥有本组的权限的时候所需要使用的,详见后面的newgrp命令;
- administrators:组的管理员,可以有多个,是一个以逗号分隔的用户名列表;组管理员可以修改组的密码和组的成员;组管理员同样具备了组成员的权限(详见members字段)。
- members:组的成员,可以有多个,是一个以逗号分隔的用户名列表;组成员在访问所属组的时候无需密码;此字段的值应该和/etc/group中的一致。
相关的命令
groupadd
简介
用于创建组。
格式
groupadd [options] group
常用选项
- -g:创建组的时候指定GID。
- -r, --system:创建系统组,GID的范围为/etc/login.defs中的变量SYS_GID_MIN~变量SYS_GID_MAX范围内的值。
groupmod
简介
用于修改组的信息。
格式
groupmod [options] GROUP
常用选项
- -g, --gid:修改组的GID。
- -n, --new-name:修改组名。
groupdel
简介
删除组。
格式
groupdel [options] GROUP
useradd
简介
- 创建新用户。
- 查看创建新用户的默认值。
- 修改创建新用户的默认值。
格式
useradd [options] LOGIN
useradd -D
useradd -D [options]
常用选项
- -u,--uid UID:指定UID。
- -g,--gid GID/GROUP:指定基本组的ID或者组名,此组需要事先存在。
- -G,--groups GROUP1[,GROUP2,...[,GROUPN]]]:指定用户所属的附加组,多个组之间使用逗号分隔。
- -c,--comment "COMMENT":指定注释信息。
- -d,--home HOME_DIR:指定用户的家目录;通过复制/etc/skel此目录并重命名实现的(skel就是skeleton,骨骼的意思);指定的家目录路径若事先存在,则不会为用户复制环境配置文件。
- -s, --shell SHELL:指定用户的默认shell,可用的所有常规shell存储在/etc/shells文件中。
- -r,--system:创建系统用户。
- -M:不创建用户的主目录,即便在/etc/login.defs文件中CREATE_HOME被设置为yes。
- -D:查看创建新用户的默认值。默认值保存在/etc/default/useradd。
- -D options:修改创建新用户的默认值。
usermod
简介
修改用户的信息。
格式
usermod [options] LOGIN
常用选项
大部分的常用选项,在useradd命令中都有说明,这里不再赘述。
- -G,--groups GROUP1[,GROUP2,...[,GROUPN]]]:修改用户的附加组,但是会替换掉原本的附加组。
- -a, --append:必须与-G,--groups一起使用,使其不会替换原本的附加组。
- -d,--home HOME_DIR:修改用户的家目录,但是默认情况下,新的家目录只有模板文件,没有原本的家目录文件。
- -m,--move-home:必须与-d,--home一起使用,将原本家目录的文件移动至新的家目录。
- -L,--lock:锁定用户的密码,禁止用户登录;即在用户原来的密码字符串之前添加一个感叹号“!”。
- -U,--unlock:解锁用户的密码,允许用户登录;就是去掉上面说的感叹号。
userdel
简介
删除用户。
格式
userdel [options] LOGIN
常用选项
- -r:删除用户时删除用户的家目录和邮件spool目录。
passwd
简介
修改用户的密码,也可以修改密码生命周期有关的参数,锁定和解锁用户密码。
默认只有root可以修改其他用户的密码,普通用户只能修改自己的密码。
查看和修改用户账户及其密码的生命周期,建议查看下文介绍的chage命令,这里不做赘述,因此相关的选项已去除
格式
不带任何选项和参数的话,表示修改当前登录用户自身的密码。
passwd [-k] [-l] [-u [-f]] [-d] [-e] [-S] [--stdin] [username]
常用选项
- -l, --lock和-u, --unlock:锁定和解锁用户。
- -d,--delete:清除某个用户的密码,仅root可用。
- -e, --expire:使一个用户的密码过期,用户下次登录会被强制要求修改密码。
- --stdin:让passwd设置的密码从标准输入来获取,这个标准输入可以来源于管道。
echo "PASSWORD" | passwd --stdin USERNAME
密码使用策略
- 使用随机密码。
- 最短长度不要低于8位。
- 应该使用大写字母、小写字母、数字和标点符号的组合。
- 定期更换。
获取随机密码的示例
[root@C7 ~]# cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 20 | head -n 5
C7OnwrVcit0qiL4A43ft
S5H1MWLKeMkJvxG6VgMU
B0IIKhoNGBfeBNljM9vB
Fiap8szMdEUwmAmOUXI9
jmuv5MmSiSgjjTffgdAs
gpasswd
简介
可用于管理/etc/group和/etc/gshadow中的字段信息。每个组拥有组管理员、组成员和组密码。
系统管理员可以使用-A选项来定义组管理员或者使用-M选项来定义组成员,系统管理员具备了组管理员和组成员的所有权限。
组管理员在调用gpasswd命令时如果仅带group参数的话,表示为组设置密码。
如果设置了组密码的话,组成员仍然可以无需密码使用newgrp至所属组;如果是非组成员的话,就必须要输入组的密码才可以newgrp了。
由于允许多人知道组密码,因此组密码是一个固有的安全问题。但是组的概念,也允许了不同的用户之间的相互协作。
格式
gpasswd [option] group
常用选项
- -a, --add user:添加用户至某个组。
- -d, --delete user:从某个组删除用户。
- -r, --remove-password:删除掉某个组的组密码;删除组密码后,只有那个组的组成员可以newgrp至那个组。
- -R, --restrict:限制对组的访问,只有拥有密码的组成员才可以使用newgrp切换至该组;组密码字段会被设置成一个感叹号;没配置密码的新用户在/etc/shadow中的密码字段的值为“!!”,该选项会认为这种情况也是有密码的,只有此字段为空才表示用户无密码,可使用passwd -d来清空用户的密码。
- -A, --administrators user,...:定义组的组管理员,可以定义多个。
- -M, --members user,...:定义组的组成员,可以定义多个。
newgrp
语法
newgrp [-] [group]
描述与示例
newgrp用于修改当前登录会话中的用户的GID。留意下面示例中新建的文件的所属组。
[zwl@C7 ~]$ id
uid=1000(zwl) gid=1000(zwl) groups=1000(zwl)
[zwl@C7 ~]$ touch test.txt
[zwl@C7 ~]$ ls -l test.txt
-rw-rw-r-- 1 zwl zwl 0 Nov 28 10:39 test.txt
[zwl@C7 ~]$ newgrp - test_group
Password:
[zwl@C7 ~]$ id
uid=1000(zwl) gid=1002(test_group) groups=1002(test_group),1000(zwl)
[zwl@C7 ~]$ touch test_newgrp.txt
[zwl@C7 ~]$ ls -l test_newgrp.txt
-rw-r--r-- 1 zwl test_group 0 Nov 28 10:40 test_newgrp.txt
如果带上了可选的标记“-”,那么用户的环境会被重新初始化,环境包含了当前的工作目录等。
group可以省略,省略表示用户切换回自己默认的定义在/etc/passwd中的GID。
[zwl@C7 ~]$ id
uid=1000(zwl) gid=1002(test_group) groups=1002(test_group),1000(zwl)
[zwl@C7 ~]$ newgrp -
[zwl@C7 ~]$ id
uid=1000(zwl) gid=1000(zwl) groups=1000(zwl),1002(test_group)
如果普通用户使用此命令的话,当遇到以下任意两种情况的时候会被要求输入组密码。
- 用户没有密码但是组有组密码。
- 用户不是组成员同时组有组密码。
如果用户不是组成员,同时组没有组密码的时候,用户newgrp至该组会被拒绝。
newgrp命令会启用一个新的bash,因此要返回之前的GID的话,要退出当前bash。可使用exit或者logout或者Ctrl+d退出。
chage
简介
专门用于查看与设置用户账户及其密码的生命周期的。
语法格式
chage [options] LOGIN
常用选项
- -d, --lastday LAST_DAY:设置场次修改密码的时间,可以是距离Unix纪元的天数,也可以是YYYY-MM-DD;LAST_DAY为0表示用户下次登录系统必须修改密码。
- -E, --expiredate EXPIRE_DATE:设置账户过期的日期,可以是距离Unix纪元的天数,也可以是YYYY-MM-DD;EXPIRE_DATE为-1表示账户永不过期。
- -I, --inactive INACTIVE:设置账户密码的失效期,INACTIVE表示天数,INACTIVE为-1表示账户密码永不失效。
- -m, --mindays MIN_DAYS:设置密码最短生命周期,MIN_DAYS为0表示用户可以随时修改密码。
- -M, --maxdays MAX_DAYS:设置密码最长生命周期,MAX_DAYS为-1表示账户密码永不过期。
- -W, --warndays WARN_DAYS:设置密码的警告周期。
- -l, --list:显示账户及其密码的生命周期。
[root@C7 ~]# chage -l zwl
Last password change : never
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
如果不带任何选项的话,则进入交互式模式。通过交互式模式来设置用户账户及其密码的生命周期。
键入新的值可用于修改,直接按回车的话表示保留当前值,中括号中值的即为当前值。
[root@C7 ~]# chage zwl
Changing the aging information for zwl
Enter the new value, or press ENTER for the default
Minimum Password Age [0]:
Maximum Password Age [99999]:
Last Password Change (YYYY-MM-DD) [-1]:
Password Expiration Warning [7]:
Password Inactive [-1]:
Account Expiration Date (YYYY-MM-DD) [-1]:
除了-l选项用于让普通用户查看自己的账户生命周期,其余的选项只能由root执行。
id
用于显示用户的UID、GID和附加组。
id [OPTION]... [USER]
省略选项的话表示UID、GID和附加组都显示,也可以只显示三者中的一种。
省略USER参数的话表示显示当前用户的信息。
[root@C7 ~]# id
uid=0(root) gid=0(root) groups=0(root)
[root@C7 ~]# id zwl
uid=1000(zwl) gid=1000(zwl) groups=1000(zwl)
- -Z, --context:用于显示当前用户的安全上下文,需要开启SELinux才能看到。
[root@C7 ~]# id -Z
id: --context (-Z) works only on an SELinux-enabled kernel
su
简介
su命令允许用户切换用户或者以指定的用户去运行命令。在指定用户的时候,还支持指定GID和附加组。
当不加任何参数的时候,su会以root用户运行一个交互式的shell。
如果运行su的用户为
- 普通用户,则要求输入目标用户的密码。
- root用户,不需要密码。
出于向后兼容性的考虑,su默认不会切换当前的目录,只会设置HOME和SHELL这两个环境变量(如果切换的目标用户不是root而是普通用户的话,还会增设USER和LOGNAME环境变量)。建议总是使用--login选项(即短选项“-”)来避免混合环境带来的副作用。
这个版本的su使用PAM用于认证、账户和会话管理。一些配置选项需要通过PAM来实现。
语法格式
su [options...] [-] [user [args...]]
常用选项
- -c command, --command=command:切换至指定的用户运行command,然后退回当前shell。
[zwl@C7 ~]$ su -c whoami
Password:
root
[zwl@C7 ~]$ whoami
zwl
- -g, --group=group:指定主要组,仅root用户可用。
- -G, --supp-group=group:指定附加组,仅root用户可用。如果-g选项省略的话,那么此处指定的第一个组会作为主要组。
- -, -l, --login:以登录式shell的方式切换用户,模拟用户真实的登录操作,有以下四步操作。
- 清除除了TERM以外的所有环境变量。
- 初始化这些环境变量HOME、SHELL、USER、LOGNAME、PATH。
- 切换至目标用户的家目录。
- 将shell的argv[0]设置为“-”使得shell变成登录式shell。
- -m, -p, --preserve-environment:保护环境,也就是说不会重新初始化这些环境变量HOME、SHELL、USER和LOGNAME。如果指定了--login选项,则该选项失效。
- -s SHELL, --shell=SHELL:指定一个shell。shell的选择按照以下顺序:
- 该选项中指定的shell。
- 如果使用了-m选项,则使用shell环境变量中指定的shell。
- 使用目标用户的/etc/passwd文件中指定的shell。
- /bin/sh。
示例
为了模拟真实的用户登录的情况,以及man手册的强烈建议,我们在切换用户的时候,都是会带上选项“-”的!
普通用户切换至root,root可省略。
[zwl@C7 ~]$ su -
Password:
Last login: Thu Nov 29 16:05:02 CST 2018 on pts/1
[root@C7 ~]# whoami
root
root用户切换至普通用户,无需密码。
[root@C7 ~]# su - zwl
Last login: Thu Nov 29 16:06:08 CST 2018 on pts/0
[zwl@C7 ~]$ whoami
zwl
切换后执行一条命令并退回当前shell。
[root@C7 ~]# su -c 'echo $HOME $LOGNAME' - zwl
/home/zwl zwl
[root@C7 ~]# echo $HOME $LOGNAME
/root root