目录
7.1用户与权限概述
用户是数据库的使用者和管理者。
MySQL通过用户的设置来控制数据库操作人员的访问与操作范围。
服务器中名为mysql的数据库,用于维护数据库的用户以及权限的控制和管理。
MySQL中的所有用户信息都保存在mysql.user数据表中。
mysql.user表中常见的字段
字段名 | 数据类型 | 默认值 |
Host | char(60) | |
User | char(32) | |
Select_priv | enum('N', 'Y') | N |
Insert_priv | enum('N', 'Y') | N |
Update_priv | enum('N', 'Y') | N |
Delete_priv | enum('N', 'Y') | N |
Create_priv | enum('N', 'Y') | N |
Drop_priv | enum('N', 'Y') | N |
Reload_priv | enum('N', 'Y') | N |
字段名 | 数据类型 | 默认值 |
Shutdown_priv | enum('N', 'Y') | N |
Process_priv | enum('N', 'Y') | N |
File_priv | enum('N', 'Y') | N |
Grant_priv | enum('N', 'Y') | N |
ssl_type | enum('','ANY','X509','SPECIFIED') | |
ssl_cipher | blob | NULL |
x509_issuer | blob | NULL |
x509_subject | blob | NULL |
max_questions | int(11) unsigned | 0 |
字段名 | 数据类型 | 默认值 |
max_updates | int(11) unsigned | 0 |
max_connections | int(11) unsigned | 0 |
max_user_connections | int(11) unsigned | 0 |
plugin | char(64) | mysql_native_password |
authentication_string | text | NULL |
password_expired | enum('N','Y') | N |
password_last_changed | timestamp | NULL |
password_lifetime | smallint(5) unsigned | NULL |
account_locked | enum('N','Y') | N |
账号字段
Host和User字段共同组成的复合主键用于区分MySQL中的账户。
User字段用于代表用户的名称。
Host字段表示允许访问的客户端IP地址或主机地址。
当Host的值为“*”时,表示所有客户端的用户都可以访问。
身份验证字段
在MySQL5.7中,mysql.user表中已不再包含Password字段,而是使用plugin和 authentication_string字段保存用户身份验证的信息。
plugin字段用于指定用户的验证插件名称。
authentication_string字段是根据plugin指定的插件算法对账户明文密码
(如123456)加密后的字符串。
安全连接字段
判断当前连接是否符合SSL安全协议。
ssl_type:用于保存安全连接的类型,它的可选值有''(空)、ANY(任意类型)、X509(X509证书)、SPECIFIED(规定的)四种。
ssl_cipher:用于保存安全加密连接的特定密码。
x509_issuer:保存由CA签发的有效的X509证书。
x509_subject:保存包含主题的有效X509证书。
资源限制字段
以“max_”开头的字段,保存对用户可使用的服务器资源的限制。
用来防止用户登录MySQL服务器后的不法或不合规范的操作浪费服务器的资源。
用户资源限制字段默认值均为 0 ,表示对此用户没有任何的资源限制。
权限字段
以“_priv”结尾的字段一共有29个,这些字段保存了用户的全局权限,如Select_priv查询权限、Insert_priv插入权限,Update_priv更新权限等。
user表对应的权限字段的数据类型都是ENUM枚举类型,取值只有N或Y两种。
N 表示该用户没有对应权限,默认值都为 N 。
Y表示该用户有对应权限。
账户锁定字段
account_locked字段用于保存当前用户是锁定、还是解锁状态。
该字段是一个枚举类型,当其值为N时表示解锁,此用户可以用于连接服务器。
当其值为Y 时表示该用户已被锁定,不能用于连接服务器使用。
7.2用户管理
(1)创建用户
CREATE USER [IF NOT EXISTS]
账户名 [用户身份验证选项][, 账户名 [用户身份验证选项]]…
[WITH 资源控制选项][密码管理选项 | 账户锁定选项]
CREATE USER 可以一次创建多个用户,多个用户之间使用逗号分隔。
账户名是由“用户名 @ 主机地址”组成 。
其余选项在创建用户时,若未设置则使用默认值。
用户名的设置不能超过 32 个字符,且区分大小写,但是主机地址不区分大小写。
CREATE USER语句选项的默认值
选项 | 默认值 |
用户身份验证选项 | 由default_authentication_plugin系统变量定义的插件进行身份验证 |
加密连接协议选项 | NONE |
资源控制选项 | N(表示无限制) |
密码管理选项 | PASSWORD EXPIRE DEFAULT |
用户锁定选项 | ACCOUNT UNLOCK |
用户身份验证选项的设置仅适用于其前面的用户名,可将其理解为某个用户的私有属性。
其余的选项对声明中的所有用户都有效,可以将其理解为全局属性。
常见的6种创建用户方式
在设置用户密码时还可以指定对密码加密的插件,只需将“IDENTIFIED BY ‘明文密码’”修改为指定的选项即可。
选项 | 描述 |
IDENTIFIED WITH 验证 插件名 | 使用指定的身份验证插件对空凭证(未设置用户密码)进行加密 |
IDENTIFIED WITH 验证 插件名 BY '明文密码' | 利用指定的身份验证插件对明文密码进行加密 |
IDENTIFIED WITH验证 插件名AS '哈希字符串' | 指定身份验证的插件,并存储哈希加密字符串 |
IDENTIFIED BY PASSWORD '哈希字符串' | 身份验证插件为默认,并存储哈希加密字符串 |
在创建用户时,可以添加WITH直接为用户指定可操作的资源范围,如登录的用户在一小时内可以查询数据的次数等。
选项 | 描述 |
MAX_QUERIES_PER_HOUR | 在任何一个小时内,允许此用户执行多少次查询 |
MAX_UPDATES_PER_HOUR | 在任何一个小时内,允许此用户执行多少次更新 |
MAX_CONNECTIONS_PER_HOUR | 在任何一个小时内,允许此用户执行多少次服务器连接 |
MAX_USER_CONNECTIONS | 限制用户同时连接服务器的最大数量 |
在创建用户时,不仅可以为用户设置密码,还可以为密码设置有效时间。
选项 | 描述 |
PASSWORD EXPIRE | 将密码标记为过期 |
PASSWORD EXPIRE DEFAULT | 根据default_password_lifetime系统变量的指定设 置密码的有效性 |
PASSWORD EXPIRE NEVER | 密码永不过期 |
PASSWORD EXPIRE INTERVAL n DAY | 将帐户密码生存期设置为 n天 |
利用ACCOUNT关键字可以为创建的用户设置是否被锁定。
它有两个可选值,分别为LOCK(锁定)和UNLOCK(解锁)。
被锁定的用户不能在客户端登录MySQL服务器。
(2)设置密码
在对MySQL中的用户进行管理时,除了创建用户的同时设置密码外,还可为没有密码的用户、密码过期的用户或为指定用户修改密码。
# ① 第1种语法(推荐)
ALTER USER 账户名 IDENTIFIED BY '明文密码';
# ② 第2种语法
SET PASSWORD [FOR账户名] = '明文密码'
# ③ 第3种语法
SET PASSWORD [FOR账户名] = PASSWORD('明文密码)
ALTER USER 是更改密码的首选 SQL 语句,推荐使用。
第 2 种语法 可能会被记录到服务器的日志或客户端的历史文件中,会有密码泄露的风险,因此建议用户尽量少的使用此方式设置密码 。
第 3 种语法 从 MySQL 5.7.6 开始已被弃用,并且将在未来的 MySQL 版本中被删除,因此不推荐使用此语法。
mysqladmin修改用户密码
在MySQL的安装目录bin下还有一个mysqladmin.exe应用程序,它通常用于执行一些管理性的工作,以及显示服务器状态等。同时,在MySQL中也可以使用该命令修改用户的密码。
mysqladmin –u 用户名 [–h 主机地址] –p password 新密码
-u : 用于指定待要修改的用户名,通常情况下指的是 root 用户。
-h : 用于指定对应的主机地址,省略时默认值为 localhost 。
-p:后面的password为关键字,而不是待修改用户的原密码。
SET PASSWORD与PASSWORD()函数
SET PASSWORD在设置密码时,添加添加与不添加PASSWORD()函数的区别:
PASSWORD() 函数 的密码根据 old_passwords 系统变量值( 0 表示 mysql_native_password 插件, 2 表示 sha256_password 插件)对指定的明文密码加密并验证;
而不 含有 PASSWORD() 函数 的 SET PASSWORD 语句是将明文密码字符串传递给用户的验证插件,并将插件返回的结果保存到 mysql.user 表的字段中。
root密码丢失找回
第1步:在MySQL的配置文件my.ini中添加skip-grant-tables选项。
第2步:重启MySQL服务
第3步:利用root用户登录,跳过密码的输入直接登录MySQL服务。
第4步:为root用户设置密码。
但是此种方式存在非常大的安全风险。慎重使用。
(3)修改用户
用户创建完成后,管理员可以通过 MySQL提供的专门SQL语句修改用户的密码、身份验证的方式、资源限制、密码的属性、以及账户的锁定和解锁的状态。
ALTER USER [IF EXISTS]
账户名 [用户身份验证选项][, 账户名 [用户身份验证选项]]…
[WITH 资源限制选项][密码管理选项 | 账户锁定选项]
ALTER USER 可同时修改一个或多个用户,多个用户之间使用逗号( , )分隔 。
语法中选项的可选值与创建用户时的选项完全相同。
每个修改的用户,都会更新其在 mysql.user 表中对应的字段值,而未修改的字段仍然保留它原来的值 。
为用户重命名
RENAME USER
旧用户名1 TO 新用户名1 [, 旧用户名2 TO 新用户名2] …
RENAME USER 在为用户重命名时,旧用户名与新用户名之间使用 TO 关键字连接。
同时为多个用户重命名时使用逗号( , )进行分割 。
(4)删除用户
DROP USER [IF EXISTS] 账户名 [, 账户名] …;
MySQL5.x 版本之后 DROP USER 语句可以同时删除一个或多个 MySQL 中的指定用户,并会同时从授权表中删除账户对应的权限行。
在 MySQL5.x 之前的版本中,在删除用户前必须先回收用户的权限。其中,账户名与创建用户的格式相同,由“用户名 @ 主机地址”组成。
7.3权限管理
(1)授予权限
当MySQL启动时会自动加载这些权限信息,并将这些权限信息读取到内存中。
数据表 | 描述 |
user | 保存用户被授予的全局权限 |
db | 保存用户被授予的数据库权限 |
tables_priv | 保存用户被授予的表权限 |
columns_priv | 保存用户被授予的列权限 |
procs_priv | 保存用户被授予的存储过程权限 |
proxies_priv | 保存用户被授予的代理权限 |
根据权限的操作内容可将权限大致分为数据权限、结构权限以及管理权限。
分类 | 权限 | 权限级别 | 描述 |
数据 权限 | SELECT | 全局、数据库、表、列 | SELECT |
UPDATE | 全局、数据库、表、列 | UPDATE | |
DELETE | 全局、数据库、表 | DELETE | |
INSERT | 全局、数据库、表、列 | INSERT | |
SHOW DATABASES | 全局 | SHOW DATABASES | |
SHOW VIEW | 全局、数据库、表 | SHOW CREATE VIEW | |
PROCESS | 全局 | SHOW PROCESSLIST | |
结构 权限 | DROP | 全局、数据库、表 | 允许删除数据库、表和视图 |
分类 | 权限 | 权限级别 | 描述 |
结构权限 | CREATE | 全局、数据库、表 | 创建数据库、表 |
CREATE ROUTINE | 全局、数据库 | 创建存储过程 | |
CREATE TABLESPACE | 全局 | 允许创建、修改或删除表空间和日志文件组 | |
CREATE TEMPORARY TABLES | 全局、数据库 | CREATE TEMPORARY TABLE | |
CREATE VIEW | 全局、数据库、表 | 允许创建或修改视图 | |
ALTER | 全局、数据库、表 | ALTER TABLE | |
ALTER ROUTINE | 全局、数据库、存储过程 | 允许删除或修改存储过程 | |
INDEX | 全局、数据库、表 | 允许创建或删除索引 |
分类 | 权限 | 权限级别 | 描述 |
结构权限 | TRIGGER | 全局、数据库、表 | 允许触发器的所有操作 |
REFERENCES | 全局、数据库、表、列 | 允许创建外键 | |
管理权限 | SUPER | 全局 | 允许使用其他管理操作,如CHANGE MASTER TO等 |
CREATE USER | 全局 | CREATE USER、DROP USER、 RENAME USER 和REVOKEALL PRIVILEGES | |
GRANT OPTION | 全局、数据库、表、存储过程、代理 | 允许授予或删除用户权限 | |
RELOAD | 全局 | FLUSH操作 | |
PROXY | 与代理的用户权限相同 | ||
REPLICATION CLIENT | 全局 | 允许用户访问主服务器或从服务器 |
分类 | 权限 | 权限级别 | 描述 |
管理权限 | REPLICATION SLAVE | 全局 | 允许复制从服务器读取的主服务器二进制日志事件 |
SHUTDOWN | 全局 | 允许使用mysqladmin shutdown | |
LOCK TABLES | 全局、数据库 | 允许在有SELECT表权限上使用LOCK TABLES |
GRANT 权限类型 [字段列表][, 权限类型 [字段列表]] ...
ON [目标类型] 权限级别
TO 账户名 [用户身份验证选项] [, 账户名 [用户身份验证选项]] ...
[REQUIRE 连接方式]
[WITH {GRANT OPTION | 资源控制选项}]
查看root用户的授权情况
mysql> SHOW GRANTS FOR 'root'@'localhost';
+---------------------------------------------------------------------+
| Grants for root@localhost |
+---------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION |
| GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION |
+---------------------------------------------------------------------+
2 rows in set (0.00 sec)
在为用户授予权限时,可以分为6个不同的级别的语法。
权限级别 | 实现语法 |
全局权限 | GRANT权限列表 ON *.* TO 账户名[WITH GRANT OPTION]; |
数据库级权限 | GRANT权限列表 ON 数据库名.* TO 账户名[WITH GRANT OPTION]; |
表级权限 | GRANT权限列表 ON 数据库名.表名 TO 账户名[WITH GRANT OPTION]; |
列级权限 | GRANT 权限类型 (字段列表) [,…]ON 数据库名.表名 TO 账户名[WITH GRANT OPTION]; |
存储过程权限 | GRANT EXECUTE|ALTER ROUTINE|CREATE ROUTINE ON {[*.*|数据库名.* ]|PROCEDURE 数据库名.存储过程} TO 账户名 [WITH GRANT OPTION]; |
代理权限 | GRANT PROXY ON 账户名 TO 账户名1 [, 账户名2] ...[WITH GRANT OPTION] |
要想使用GRANT语句为用户授权,必须要拥有GRANT OPTION权限;且在启用read_only系统变量时,还必须要拥有SUPER权限。
(2)回收权限
# ① 回收指定用户的指定权限
REVOKE 权限类型 [(字段列表)] [, 权限类型[(字段列表)]] …
ON [目标类型] 权限级别 FROM 账户名 [, 账户名] …
# ② 回收表7-7中的所有权限以及可为其他用户授权的权限
REVOKE ALL [PRIVILEGES], GRANT OPTION FROM 账户名 [, 账户名] …
# ③ 回收用户的代理权限
REVOKE PROXY ON 账户名 FROM 账户名1 [, 账户名2] …
(3)刷新权限
刷新权限:指的是从系统数据库mysql中的权限表中重新加载用户的权限。
原因在于:GRANT、CREATE USER等操作会将服务器的缓存信息保存到内存中,而REVOKE、DROP USER操作并不会同步到内存中,因此可能会造成服务器内存的消耗,所以在REVOKE、DROP USER后推荐读者使用MySQL提供的“FLUSH PRIVILEGES”重新加载用户的权限。
# 方式1
FLUSH PRIVILEGES;
# 方式2
mysqladmin -uroot -p reload
# 方式3
mysqladmin -uroot -p flush-privileges