目录
1 权限与安全
1.1 权限表
1.2 账户管理
1.3 权限管理
1.4 访问控制
1.5 提升安全性
1 权限与安全
内容导航 》
- 了解什么是权限表
- 掌握权限表的用法
- 掌握账户管理的方法
- 掌握权限管理的方法
- 掌握访问控制的方法
1.1 权限表
MySQL 服务器通过权限表来控制用户对数据库的访问,权限表存放在 MySQL 数据库中,由 mysql_install_db 脚本初始化。存储账户权限信息的表主要有 user、db、host、tables_priv、columns_priv 和 procs_priv ,但在 MySQL 5.6.7 版本中,host 表已经被删除。
- user 表
user 表是 MySQL 中最重要的权限表,记录允许连接到服务器的账号信息,里面的权限是全局的。
mysql> SHOW CREATE TABLE mysql.user \G;
*************************** 1. row ***************************
Table: user
Create Table: CREATE TABLE `user` (
`Host` char(255) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT '',
`User` char(32) COLLATE utf8_bin NOT NULL DEFAULT '',
`Select_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Insert_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Update_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Delete_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Create_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Drop_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Reload_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Shutdown_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Process_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`File_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Grant_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`References_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Index_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Alter_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Show_db_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Super_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Lock_tables_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Execute_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Repl_slave_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Repl_client_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Create_view_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Show_view_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Create_routine_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Alter_routine_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Create_user_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Event_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Trigger_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Create_tablespace_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`ssl_type` enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`ssl_cipher` blob NOT NULL,
`x509_issuer` blob NOT NULL,
`x509_subject` blob NOT NULL,
`max_questions` int unsigned NOT NULL DEFAULT '0',
`max_updates` int unsigned NOT NULL DEFAULT '0',
`max_connections` int unsigned NOT NULL DEFAULT '0',
`max_user_connections` int unsigned NOT NULL DEFAULT '0',
`plugin` char(64) COLLATE utf8_bin NOT NULL DEFAULT 'caching_sha2_password',
`authentication_string` text COLLATE utf8_bin,
`password_expired` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`password_last_changed` timestamp NULL DEFAULT NULL,
`password_lifetime` smallint unsigned DEFAULT NULL,
`account_locked` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Create_role_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Drop_role_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Password_reuse_history` smallint unsigned DEFAULT NULL,
`Password_reuse_time` smallint unsigned DEFAULT NULL,
`Password_require_current` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci DEFAULT NULL,
`User_attributes` json DEFAULT NULL,
PRIMARY KEY (`Host`,`User`)
) /*!50100 TABLESPACE `mysql` */ ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin STATS_PERSISTENT=0 ROW_FORMAT=DYNAMIC COMMENT='Users and global privileges'
1 row in set (0.00 sec)
*************************** 2. row ***************************
Host: 客户端ip段限制
User: 用户名
Select_priv: 查询权限
Insert_priv: 写入权限
Update_priv: 更新权限
Delete_priv: 删除权限
Create_priv: 创建库和表
Drop_priv: 删除库和表
Reload_priv: 执行刷新和重新加载mysql所用各种内部缓存的特定命令,包含日志,权限,主机,查询和表
Shutdown_priv: 关闭mysql服务器
Process_priv: 通过show processlist查看其他用户的进程
File_priv: 执行select into outfile 和load data infile 导入和导出数据命令
Grant_priv: 将自己的权限再授予其他用户
References_priv: 创建外键约束
Index_priv: 对索引进行增删查
Alter_priv: 重命名和修改表结构
Show_db_priv: 查看服务器上所有数据库的名字
Super_priv: 执行某些强大的管理功能,如:kill命令删除用户进程;使用set golbal修改全局变量;执行关于复制和日志的各种命令(超级功能)
Create_tmp_table_priv: 创建临时表
Lock_tables_priv: 使用lock tables 命令
Execute_priv: 执行存储过程
Repl_slave_priv: 读取用于维护复制数据库环境的二进制日志文件
Repl_client_priv: 确定复制从服务器和主服务器的位置
Create_view_priv: 创建视图
Show_view_priv: 查看视图
Create_routine_priv: 更改或放弃存储过程和函数
Alter_routine_priv: 修改或删除存储过程及函数
Create_user_priv: 执行create user新建用户命令
Event_priv: 创建,修改,删除事件
Trigger_priv: 创建,删除触发器
Create_tablespace_priv: 创建表空间
ssl_type: 支持ssl标准加密安全字段
ssl_cipher: 支持ssl标准加密安全字段
x509_issuer: 支持x509标准字段
x509_subject: 支持x510标准字段
max_questions: 每小时允许执行多少次查询
max_updates: 每小时可执行多少次更新,0标识无限制
max_connections: 每小时可以建立多少次链接
max_user_connections: 单用户可以同时具有的连接数
plugin: 引用plugins以进行用户连接时的密码验证,plugin创建外部/代理用户
authentication_string: 密码
password_expired: 密码过期,Y说明已过期
mysql> SELECT * FROM mysql.user;
+-----------+------------------+-------------+-------------+-------------+-------------+-------------+-----------+-------------+---------------+--------------+-----------+------------+-----------------+------------+------------+--------------+------------+-----------------------+------------------+--------------+-----------------+------------------+------------------+----------------+---------------------+--------------------+------------------+------------+--------------+------------------------+----------+------------------------+--------------------------+----------------------------+---------------+-------------+-----------------+----------------------+-----------------------+------------------------------------------------------------------------+------------------+-----------------------+-------------------+----------------+------------------+----------------+------------------------+---------------------+--------------------------+-----------------+
| Host | User | Select_priv | Insert_priv | Update_priv | Delete_priv | Create_priv | Drop_priv | Reload_priv | Shutdown_priv | Process_priv | File_priv | Grant_priv | References_priv | Index_priv | Alter_priv | Show_db_priv | Super_priv | Create_tmp_table_priv | Lock_tables_priv | Execute_priv | Repl_slave_priv | Repl_client_priv | Create_view_priv | Show_view_priv | Create_routine_priv | Alter_routine_priv | Create_user_priv | Event_priv | Trigger_priv | Create_tablespace_priv | ssl_type | ssl_cipher | x509_issuer | x509_subject | max_questions | max_updates | max_connections | max_user_connections | plugin | authentication_string | password_expired | password_last_changed | password_lifetime | account_locked | Create_role_priv | Drop_role_priv | Password_reuse_history | Password_reuse_time | Password_require_current | User_attributes |
+-----------+------------------+-------------+-------------+-------------+-------------+-------------+-----------+-------------+---------------+--------------+-----------+------------+-----------------+------------+------------+--------------+------------+-----------------------+------------------+--------------+-----------------+------------------+------------------+----------------+---------------------+--------------------+------------------+------------+--------------+------------------------+----------+------------------------+--------------------------+----------------------------+---------------+-------------+-----------------+----------------------+-----------------------+------------------------------------------------------------------------+------------------+-----------------------+-------------------+----------------+------------------+----------------+------------------------+---------------------+--------------------------+-----------------+
| localhost | mysql.infoschema | Y | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | | 0x | 0x | 0x | 0 | 0 | 0 | 0 | caching_sha2_password | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED | N | 2022-05-09 10:33:37 | NULL | Y | N | N | NULL | NULL | NULL | NULL |
| localhost | mysql.session | N | N | N | N | N | N | N | Y | N | N | N | N | N | N | N | Y | N | N | N | N | N | N | N | N | N | N | N | N | N | | 0x | 0x | 0x | 0 | 0 | 0 | 0 | caching_sha2_password | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED | N | 2022-05-09 10:33:37 | NULL | Y | N | N | NULL | NULL | NULL | NULL |
| localhost | mysql.sys | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | N | | 0x | 0x | 0x | 0 | 0 | 0 | 0 | caching_sha2_password | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED | N | 2022-05-09 10:33:37 | NULL | Y | N | N | NULL | NULL | NULL | NULL |
| localhost | root | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | | 0x | 0x | 0x | 0 | 0 | 0 | 0 | caching_sha2_password | $A$005${7;+ `hpIdY"9N6mhpZ/.cAOoPJZz0aLxOHKi7OwNy7DGZJN7I2xZ22 | N | 2022-05-09 10:33:41 | NULL | N | Y | Y | NULL | NULL | NULL | NULL |
+-----------+------------------+-------------+-------------+-------------+-------------+-------------+-----------+-------------+---------------+--------------+-----------+------------+-----------------+------------+------------+--------------+------------+-----------------------+------------------+--------------+-----------------+------------------+------------------+----------------+---------------------+--------------------+------------------+------------+--------------+------------------------+----------+------------------------+--------------------------+----------------------------+---------------+-------------+-----------------+----------------------+-----------------------+------------------------------------------------------------------------+------------------+-----------------------+-------------------+----------------+------------------+----------------+------------------------+---------------------+--------------------------+-----------------+
4 rows in set (0.00 sec)
(1)用户列
user 表的用户列包括 host、user、authentication_string,分别表示主机名、用户名和加密后的密码。其中 host 和 user 列为表的主键。当用户与服务器建立连接时,输入的账户信息中的用户名、主机名、密码必须匹配 user 表中的某行的对应字段,只有三个值都匹配时,才允许建立连接。
- Host: 客户端 ip 段限制
- User: 用户名
- authentication_string: 密码
(2)权限列
权限列的字段决定了用户的权限,描述了在全局范围内允许对数据库进行的操作。包括查询权限、修改权限、删除权限等普通权限,还包括了关闭服务器、超级权限和加载用户等高级权限。普通权限用于操作数据库,高级权限用于管理数据库。
- Select_priv: 查询权限
- Insert_priv: 写入权限
- Update_priv: 更新权限
- Delete_priv: 删除权限
- Create_priv: 创建库和表
- Drop_priv: 删除库和表
- Reload_priv: 执行刷新和重新加载mysql所用各种内部缓存的特定命令,包含日志,权限,主机,查询和表
- Shutdown_priv: 关闭 mysql 服务器
- Process_priv: 通过 show processlist 查看其他用户的进程
- File_priv: 执行 select into outfile 和load data infile 导入和导出数据命令
- Grant_priv: 将自己的权限再授予其他用户
- References_priv: 创建外键约束
- Index_priv: 对索引进行增删查
- Alter_priv: 重命名和修改表结构
- Show_db_priv: 查看服务器上所有数据库的名字
- Super_priv: 执行某些强大的管理功能,如:kill 命令删除用户进程;使用 set golbal 修改全局变量;执行关于复制和日志的各种命令(超级功能)
- Create_tmp_table_priv: 创建临时表
- Lock_tables_priv: 使用 lock tables 命令
- Execute_priv: 执行存储过程
- Repl_slave_priv: 读取用于维护复制数据库环境的二进制日志文件
- Repl_client_priv: 确定复制从服务器和主服务器的位置
- Create_view_priv: 创建视图
- Show_view_priv: 查看视图
- Create_routine_priv: 更改或放弃存储过程和函数
- Alter_routine_priv: 修改或删除存储过程及函数
- Create_user_priv: 执行 create user 新建用户命令
- Event_priv: 创建,修改,删除事件
- Trigger_priv: 创建,删除触发器
- Create_tablespace_priv: 创建表空间
(3) 安全列
安全列只有六个字段,其中两个是 ssl 相关的,两个是 x509 相关的,另外两个是授权插件相关。
- ssl_type: 支持ssl标准加密安全字段
- ssl_cipher: 支持ssl标准加密安全字段
- x509_issuer: 支持x509标准字段
- x509_subject: 支持x510标准字段
- plugin: 引用plugins以进行用户连接时的密码验证,plugin创建外部/代理用户
(4)资源控制列
- max_questions: 每小时允许执行多少次查询
- max_updates: 每小时可执行多少次更新,0标识无限制
- max_connections: 每小时可以建立多少次链接
- max_user_connections: 单用户可以同时具有的连接数
- db 表
db 表中存储了用户对某个数据库的操作权限,决定用户能从哪个主机存取哪个数据库。
mysql> SHOW CREATE TABLE mysql.db \G;
*************************** 1. row ***************************
Table: db
Create Table: CREATE TABLE `db` (
`Host` char(255) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT '',
`Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
`User` char(32) COLLATE utf8_bin NOT NULL DEFAULT '',
`Select_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Insert_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Update_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Delete_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Create_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Drop_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Grant_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`References_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Index_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Alter_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Lock_tables_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Create_view_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Show_view_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Create_routine_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Alter_routine_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Execute_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Event_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
`Trigger_priv` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
PRIMARY KEY (`Host`,`Db`,`User`),
KEY `User` (`User`)
) /*!50100 TABLESPACE `mysql` */ ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin STATS_PERSISTENT=0 ROW_FORMAT=DYNAMIC COMMENT='Database privileges'
1 row in set (0.00 sec)
user 表中的权限是针对所有数据库的,如果希望用户只具有某些数据库的某些权限,可以将 user 表中的对应字段设置为 N ,然后在 db 表中设置相应权限为 Y 。
- tables_priv 和 columns_priv 表
tables_priv 表用来设置具体用户对表的操作权限,columns_priv 表用来设置具体用户对表中列的操作权限。
mysql> SHOW CREATE TABLE mysql.tables_priv \G;
*************************** 1. row ***************************
Table: tables_priv
Create Table: CREATE TABLE `tables_priv` (
`Host` char(255) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT '',
`Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
`User` char(32) COLLATE utf8_bin NOT NULL DEFAULT '',
`Table_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
`Grantor` varchar(288) COLLATE utf8_bin NOT NULL DEFAULT '',
`Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT '',
PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`),
KEY `Grantor` (`Grantor`)
) /*!50100 TABLESPACE `mysql` */ ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin STATS_PERSISTENT=0 ROW_FORMAT=DYNAMIC COMMENT='Table privileges'
1 row in set (0.00 sec)
ERROR:
No query specified
mysql> SHOW CREATE TABLE mysql.columns_priv \G;
*************************** 1. row ***************************
Table: columns_priv
Create Table: CREATE TABLE `columns_priv` (
`Host` char(255) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT '',
`Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
`User` char(32) COLLATE utf8_bin NOT NULL DEFAULT '',
`Table_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
`Column_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
`Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT '',
PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`,`Column_name`)
) /*!50100 TABLESPACE `mysql` */ ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin STATS_PERSISTENT=0 ROW_FORMAT=DYNAMIC COMMENT='Column privileges'
1 row in set (0.00 sec)
ERROR:
No query specified
- procs_priv 表
procs_priv 表可以对存储过程和存储函数设置操作权限。
mysql> SHOW CREATE TABLE mysql.procs_priv \G;
*************************** 1. row ***************************
Table: procs_priv
Create Table: CREATE TABLE `procs_priv` (
`Host` char(255) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT '',
`Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
`User` char(32) COLLATE utf8_bin NOT NULL DEFAULT '',
`Routine_name` char(64) CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`Routine_type` enum('FUNCTION','PROCEDURE') COLLATE utf8_bin NOT NULL,
`Grantor` varchar(288) COLLATE utf8_bin NOT NULL DEFAULT '',
`Proc_priv` set('Execute','Alter Routine','Grant') CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`Host`,`Db`,`User`,`Routine_name`,`Routine_type`),
KEY `Grantor` (`Grantor`)
) /*!50100 TABLESPACE `mysql` */ ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin STATS_PERSISTENT=0 ROW_FORMAT=DYNAMIC COMMENT='Procedure privileges'
1 row in set (0.00 sec)
ERROR:
No query specified
1.2 账户管理
1.2.1 登录和退出 MySQL 服务器
登录命令:MySQL [-h hostname | ip] -u username -p[password] [-P port] [database_name] [-e]
/*
(1) -h 主机名,可以使用该参数指定主机名或 ip , 如果不指定,默认是 localhost 。
(2) -u 用户名,可以使用该参数指定用户名。
(3) -p 密码,可以使用该参数指定登录密码。如果该参数后面有一段字段,则该段字符串将作为用户的密码直接登录。如果后面没有内容,则录的时候会提示输入密码。注意:该参数后面的字符串和-p之间不能有空格。
(4) -P 端口号,该参数后面接 MySQL 服务器的端口号,默认为 3006 。
(5) -e 执行 SQL 语句。如果指定了该参数,将在登录后执行 -e 后面的命令或 SQL 语句并退出。
(6) 数据库名,可以在命令的最后指定数据库名。
*/
退出命令:Ctrl + c 或 quit 即可退出 MySQL 。
C:\Users\Administrator>mysql -h localhost -u tx -proot -P 3306
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 19
Server version: 8.0.29 MySQL Community Server - GPL
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
C:\Users\Administrator>mysql -h localhost -u tx -p -P 3306 -e "SHOW DATABASES";
Enter password: ****
+--------------------+
| Database |
+--------------------+
| information_schema |
+--------------------+
C:\Users\Administrator>
1.2.2 新建普通用户
使用 CREATE USER 语句创建用户
CREATE USER user_specification [user_specification2, ..., user_specificationn]
/*
user_specification: 'user'@'host'
[IDENTIFIED BY 'password' | IDENTIFIED WITH auth_plugin [AS 'auth_string']]
user 表示创建的用户名称,host 表示允许登录的用户主机名称,
如果不指定host,主机名默认为 '%',代表对所有的主机开放权限;
IDENTIFIED BY 表示用来设置用户的密码,
'password' 表示用户登录时的普通明文密码,如果不指定该参数,则代表用户不需要密码登录;
IDENTIFIED WITH 为用户指定一个身份验证的插件,
auth_plugin 代表插件的名字,
插件的名称可以是一个带单引号的字符串或者带双引号的字符串,
'auth_string' 是传递给插件的参数。
*/
直接操作 MySQL 用户表
使用 CREATE USER 创建新用户时,实际上都是在 user 表中添加一条新的记录。所以我们可以使用 INSERT 语句向 user 表中直接插入一条记录创建一个新用户。使用 INSERT 语句,必须拥有对 MySQL.user 表的 INSERT 权限。
mysql> SELECT ssl_cipher, x509_issuer, x509_subject FROM MySQL.user;
+------------------------+--------------------------+----------------------------+
| ssl_cipher | x509_issuer | x509_subject |
+------------------------+--------------------------+----------------------------+
| 0x | 0x | 0x |
| 0x | 0x | 0x |
| 0x | 0x | 0x |
| 0x | 0x | 0x |
+------------------------+--------------------------+----------------------------+
4 rows in set (0.00 sec)
INSERT INTO MySQL.user(Host, User, authentication_string, ssl_cipher, x509_issuer, x509_subject)
VALUES('host', 'username', MD5('password'), '0x', '0x', '0x')
注意:因为 user 表没有为 ssl_cipher, x509_issuer, x509_subject 这三个字段设置默认值,所以直接插入表记录新增用户的方式必须指定这三个值。
1.2.3 删除普通用户
在 MySQL 中,可以通过 DROP USER 语句删除用户,也可以直接通过DELETE 从MySQL.user 表里删除对应的记录来删除用户。
DROP USER 'user'@'host' [, 'user2'@'host2', ..., 'usern'@'hostn']
DROP USER 语句用于删除一个或多个 MySQL 账户,必须有 MySQL 数据库的全局 CREATE USER 权限或 DELETE 权限。
DROP USER 不能自动关闭任何打开的用户对话,而且,如果有用户打开的对话,此时取消用户,命令不会立即生效,知道用户对话被关闭后才生效,一旦对话被关闭,用户也被取消,此时用户再试图登录就会失败。
使用 DELETE 语句删除用户
DELETE FROM MySQL.user WHERE host = 'hostname' and user = 'username'
1.2.4 root 用户修改自己的密码
root 用户的安全对于保证 MySQL 的安全非常重要,因为 root 用户拥有很高的权限。可以直接通过修改 user 表来改变 root 的密码。一般,只给 root 分配能够在 user 表上增删改的权限。
UPDATE MySQL.user SET authentication_string = MD5('password') WHERE User = 'root' and Host = 'localhost'
执行 UPDATE 语句后,需要执行 FLUSH PRIVILEGES 语句重新加载用户权限。
1.2.5 root 用户修改普通用户的密码
可以直接使用 SET 语句修改普通用户的密码
SET PASSWORD FOR 'user'@'host' = 'password'
执行 UPDATE 语句后,需要执行 FLUSH PRIVILEGES 语句重新加载用户权限。
也可以使用 UPDATE 语句从 MySQL.user 表中直接修改普通用户的密码。
C:\Users\Administrator>mysql -h localhost -u root -p -P 3306 -e "SELECT * FROM MySQL.user \G;";
Enter password: *************
*************************** 1. row ***************************
Host: %
User: tx
Select_priv: N
Insert_priv: N
Update_priv: N
Delete_priv: N
Create_priv: N
Drop_priv: N
Reload_priv: N
Shutdown_priv: N
Process_priv: N
File_priv: N
Grant_priv: N
References_priv: N
Index_priv: N
Alter_priv: N
Show_db_priv: N
Super_priv: N
Create_tmp_table_priv: N
Lock_tables_priv: N
Execute_priv: N
Repl_slave_priv: N
Repl_client_priv: N
Create_view_priv: N
Show_view_priv: N
Create_routine_priv: N
Alter_routine_priv: N
Create_user_priv: N
Event_priv: N
Trigger_priv: N
Create_tablespace_priv: N
ssl_type:
ssl_cipher: 0x
x509_issuer: 0x
x509_subject: 0x
max_questions: 0
max_updates: 0
max_connections: 0
max_user_connections: 0
plugin: caching_sha2_password
authentication_string: $A$005$*!p*.Us7?WxP=Kjy2uIG6/bgv1b6lHwe0F.MZbCpJbUdMXd/SFsYXS2g3
password_expired: N
password_last_changed: 2022-06-03 08:06:37
password_lifetime: NULL
account_locked: N
Create_role_priv: N
Drop_role_priv: N
Password_reuse_history: NULL
Password_reuse_time: NULL
Password_require_current: NULL
User_attributes: NULL
可以看到,默认的 MySQL 内置的加密算法是 SHA_2, 现在用另外的算法为我们的密码加密。
mysql> UPDATE MySQL.user SET authentication_string = MD5('root') WHERE User = 'tx' AND Host = '%';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
执行 UPDATE 语句后,需要执行 FLUSH PRIVILEGES 语句重新加载用户权限。但是注意这里,我没执行 FLUSH PRIVILEGES 命令之前,用户 tx 还是可以正常登录的:
C:\Users\Administrator>mysql -h localhost -u tx -p -P 3306 -e "SHOW DATABASES";
Enter password: ****
+--------------------+
| Database |
+--------------------+
| information_schema |
+--------------------+
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)
但是我执行 FLUSH PRIVILEGES 之后,用户 tx 就登录不上了:
C:\Users\Administrator>mysql -h localhost -u tx -p -P 3306 -e "SHOW DATABASES";
Enter password: ****
ERROR 1045 (28000): Access denied for user 'tx'@'localhost' (using password: YES)
这个应该很好想到,因为之前的密码加密使用的是 MySQL 内置的 SHA2 加密插件,现在我用 MD5() 加密函数修改了我们的密码,但是没有更换我们的插件,所以我们应该能想到,tx 正常是登录不上了的,除非我们给他换一下加解密插件,先查看目前我们已经安装的加密插件:
mysql> SHOW PLUGINS;
+---------------------------------+----------+--------------------+---------+---------+
| Name | Status | Type | Library | License |
+---------------------------------+----------+--------------------+---------+---------+
| binlog | ACTIVE | STORAGE ENGINE | NULL | GPL |
| mysql_native_password | ACTIVE | AUTHENTICATION | NULL | GPL |
| sha256_password | ACTIVE | AUTHENTICATION | NULL | GPL |
| caching_sha2_password | ACTIVE | AUTHENTICATION | NULL | GPL |
| sha2_cache_cleaner | ACTIVE | AUDIT | NULL | GPL |
| daemon_keyring_proxy_plugin | ACTIVE | DAEMON | NULL | GPL |
| CSV | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MEMORY | ACTIVE | STORAGE ENGINE | NULL | GPL |
| InnoDB | ACTIVE | STORAGE ENGINE | NULL | GPL |
| INNODB_TRX | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMP | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMP_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMPMEM | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMPMEM_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMP_PER_INDEX | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMP_PER_INDEX_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_BUFFER_PAGE | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_BUFFER_PAGE_LRU | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_BUFFER_POOL_STATS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_TEMP_TABLE_INFO | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_METRICS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_FT_DEFAULT_STOPWORD | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_FT_DELETED | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_FT_BEING_DELETED | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_FT_CONFIG | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_FT_INDEX_CACHE | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_FT_INDEX_TABLE | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_TABLES | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_TABLESTATS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_INDEXES | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_TABLESPACES | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_COLUMNS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_VIRTUAL | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CACHED_INDEXES | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_SESSION_TEMP_TABLESPACES | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| MyISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MRG_MYISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |
| PERFORMANCE_SCHEMA | ACTIVE | STORAGE ENGINE | NULL | GPL |
| TempTable | ACTIVE | STORAGE ENGINE | NULL | GPL |
| ARCHIVE | ACTIVE | STORAGE ENGINE | NULL | GPL |
| BLACKHOLE | ACTIVE | STORAGE ENGINE | NULL | GPL |
| FEDERATED | DISABLED | STORAGE ENGINE | NULL | GPL |
| ngram | ACTIVE | FTPARSER | NULL | GPL |
| mysqlx_cache_cleaner | ACTIVE | AUDIT | NULL | GPL |
| mysqlx | ACTIVE | DAEMON | NULL | GPL |
+---------------------------------+----------+--------------------+---------+---------+
45 rows in set (0.01 sec)
没有我们想要的 MD5 的加解密插件,先下载一个:
//todo:
然后为用户 tx 更换密码验证的插件:
//todo:
1.3 权限管理
权限管理主要是针对登录到 MySQL 的用户进行权限验证。所有用户的权限都保存在 MySQL 的权限表中,不合理的权限规划会给 MySQL 服务器带来安全隐患。数据库管理员要对所有用户的权限进行合理的规划管理。MySQL 权限系统的主要功能是证实连接到一台给定主机的用户,并赋予该用户在数据库上的 SELECT 、INSERT、UPDATE 和 DELETE 权限。
1.3.1 MySQL 的各种权限
账户权限信息被存储在 MySQL 库的 user、db、tables_priv、columns_priv 和 procs_priv 表中。MySQL 在启动时,服务器将这些数据表中的权限信息读入内存。
MySQL.user 表中可分配的权限
权限 | user 表中对应的列 | 权限的范围 |
CREATE | Create_priv | 数据库、表或索引 |
DROP | Drop_priv | 数据库、表或索引 |
CRANT | Grant_priv | 数据库、表或存储过程 |
REFERENCES | References_priv | 数据库或表 |
EVENT | Event_priv | 数据库 |
ALTER | Alter_priv | 数据库 |
INSERT | Insert_priv | 表 |
DELETE | Delete_priv | 表 |
UPDATE | Update_priv | 表或列 |
SELECT | Select_priv | 表或列 |
INDEX | Index_priv | 表 |
CREATE TEMPORARY TABLES | Create_tmp_tables_priv | 表 |
LOCK TABLES | Lock_tables_priv | 表 |
TRIGGER | Trigger_priv | 表 |
CREATE VIEW | Create_view_priv | 视图 |
SHOW VIEW | Show_view_priv | 视图 |
CREATE ROUTINE | Create_routine_priv | 存储过程和函数 |
ALTER ROUTINE | Alter_routine_priv | 存储过程和函数 |
EXECUTE | Execucte_priv | 存储过程和函数 |
FILE | File_priv | 访问服务器上的文件 |
RELOAD | Reload_priv | 访问服务器上的文件(相关命令 FLUSH HOSTS、FLUSH LOGS、FLUSH PRIVILEGES、FLUSH STATUS、FLUSH TABLES、FLUSH THREAD) |
CREATE TABLESPACE | Create_tablespace_priv | 服务器管理 |
CREATE USER | Create_user_priv | 服务器管理 |
PROCESS | Process_priv | 服务器管理 |
REPLICATION CLIENT | Repl_client_priv | 服务器管理 |
REPLICATION SLAVE | Repl_slave_priv | 服务器管理 |
SHOW DATABASES | Show_db_priv | 服务器管理 (相关命令 SHUTDOWN) |
SHUTDOWN | Shutdown_priv | 服务器管理(相关命令 SHOW PROCESSLIST) |
SUPER | Super_priv | 服务器管理(相关命令 KILL) |
1.3.2 授权
授权就是为某个用户授予权限。合理的授权可以保证数据库安全。MySQL 中可以使用 GRANT 语句为用户授予权限。授予的权限可以分为多个层级:
1. 全局层级
全局权限适用于一个给定的服务器中的所有数据库。这些权限存储在 MySQL.user 表中。 GRANT ALL ON *.* 和 REVOKE ALL ON *.* 只授予和撤销全局权限。
2. 数据库层级
数据库权限适用于一个给定的数据库中的所有目标。这些权限在 MySQL.db 表中。GRANT ALL ON db_name.* 和 REVOKE ALL ON db_name.*只授予和撤销数据库权限。
3. 表层级
表权适用于一个表中给定的所有列。这些权限在 MySQL.tables_priv 表中。GRANT ALL ON db_name.table_name.* 和 REVOKE ALL ON db_name.table_name.* 授予和撤销表权限。
4. 列层级
列权适用于一个给定表中的单一列。这些权限存储在 MySQL.column_priv 表中。当使用 REVOKE 时,必须指定与被授权列相同的列。
5. 子程序层级
CREATE ROUTINE 、ALTER ROUTINE、EXECUTE 和 GRANT 权限适用于已存储的子程序,这些权限可以被授予为全局层级和数据库层级。而且除了 CREATE ROUTINE 外,这些权限可以被授予在子程序层级,并存储在 M有SQL.procs_priv 表中。
在 MySQL 中,必须是拥有 GRANT 权限的用户才可以执行 GRANT 或 REVOKE 语句:
GRANT priv_type [(columns)] [, priv_type2 [(columns2), ..., priv_typen [(columnsn)]]
ON [object_type] TO 'user'@'host' [, user2'@'host2', ..., usern'@'hostn']
[WITH with_option]
/*
priv_type: 表示权限类型
columns: 表示作用到哪些列上,不写则代表所有列
object_type: 表示在哪个库哪个表或子程序上,*.* 代表全局所有库所有表
with_option:
· CRANT OPTION: 表示被授权的用户具有授权权限,可以将自己拥有的权限授予其他人
· MAX_QUERIES_PER_HOUR count: 每个小时最多可以执行 count 次查询
· MAX_UPDATES_PER_HOUR count: 每个小时最多可以执行 count 次更新
· MAX_CONNECTIONS_PER_HOUR count: 每个小时最多可以建立 count 个连接
· MAX_USER_CONNECTIONS count: 单个用户同时最多可以建立 count 个连接
*/
1.3.3 收权
使用 REVOKE 收回权限之后,用户账户的记录将从 db、tables_priv、columns_priv 和 procs_priv 表中删除,但是账号记录仍然在 user 表中存在,使用 DROP USER 语句从 user 表中删除用户。
在将用户账户从 user 表中删除之前,应收回相应用户的所有权限。REVOKE 语句有两种格式:
第一种语法是收回用户的所有权限:
REVOKE ALL PRIVILEGES, GRANT OPTION
FROM 'user'@'host' [, user2'@'host2', ..., usern'@'hostn']
另一种语法为长格式:
REVOKE priv_type [(columns)] [, priv_type2 [(columns2), ..., priv_typen [(columnsn)]]
ON [object_type] FROM 'user'@'host' [, user2'@'host2', ..., usern'@'hostn']
1.3.4 查看权限
SHOW GRANTS FOR 'user'@'host'
mysql> SHOW GRANTS FOR 'tx'@'%';
+--------------------------------+
| Grants for tx@% |
+--------------------------------+
| GRANT USAGE ON *.* TO `tx`@`%` |
+--------------------------------+
1 row in set (0.01 sec)
1.4 访问控制
MySQL 的访问控制分为两个阶段:连接核实阶段和请求核实阶段。
1.4.1 连接核实阶段
当连接 MySQL 服务器时,服务器基于用户的身份以及用户是否能通过正确的密码身份验证来接受或拒绝连接,客户端用户连接请求中会提供用户名称、主机地址名和密码。MySQL 使用 user 表中的 Host、User 和 authentication_string 字段执行身份验证,服务器只有在 user 表记录的 Host 和 User 字段匹配客户端主机名和用户名并且密码验证通过后才会接受连接。如果连接核实没有通过,服务器完全拒绝访问;否则,服务器接收连接,然后进入阶段 2 等待用户请求。
1.4.2 请求核实阶段
建立了连接之后,服务器进入访问控制阶段的阶段 2。对在此连接上的每个请求,服务器检查用户要执行的操作,然后检查是否有足够的权限来执行它。这正是授权表中权限列发挥作用的地方。这些权限可以来自 MySQL 库的 user、db、tables_priv、columns_priv 和 procs_priv 表。
确认权限时,MySQL 首先检查 user 表,如果指定的权限没有在 user 表中被授权,MySQL将检查 db 表,db 表是下一安全层级,其中的权限现定于数据库层级,如果在该层级没有找到限定的权限,则 MySQL 继续检查 tables_priv 和 columns_priv 表,如此往下,如果所有权限表都检查完毕,还是没有找到允许的权限操作,MySQL 将返回错误信息,用户请求的操作不能执行,操作失败。MySQL 通过向下层级的顺序检查权限表,但并不是所有的请求都要执行该过程。例如,一个用户登录到 MySQL 只是要执行对 MySQL 的管理操作,此时,只涉及管理权限,因此 MySQL 只检查 user 表。
1.5 提升安全性
MySQL 进一步提升了安全性,主要表现如下:
1.5.1 AES 256 加密
MySQL 8.0 支持多种 AES 256 加解密模式,通过更大的密钥长度和不同的块模式增强了高级加密标准,主要通过加密函数 AES_ENCODE() 和解密函数 AES_DECODE() 来提升安全性。
AES_ENCRYPT(password_str, password_key)
AES_DECRYPT(password_str, password_key)
1.5.2 密码到期更换策略
MySQL 8.0 允许数据库管理员手动设置账户密码过期时间,任何密码超期的账户想要登录 MySQL 都必须更改密码。通过设置 default_password_lifetime 可以设置新账户过期时间。
mysql> SHOW VARIABLES LIKE 'default_password_lifetime';
+---------------------------+-------+
| Variable_name | Value |
+---------------------------+-------+
| default_password_lifetime | 0 |
+---------------------------+-------+
1 row in set, 1 warning (0.00 sec)
mysql> SET PERSIST default_password_lifetime = 260;
Query OK, 0 rows affected (0.01 sec)
mysql> SHOW VARIABLES LIKE 'default_password_lifetime';
+---------------------------+-------+
| Variable_name | Value |
+---------------------------+-------+
| default_password_lifetime | 260 |
+---------------------------+-------+
1 row in set, 1 warning (0.00 sec)
查看系统中 litaixun 账户过期时间:
mysql> SELECT User, Host, Password_last_changed, password_lifetime, password_expired FROM MySQL.user WHERE User = 'litaixun' \G;
*************************** 1. row ***************************
User: litaixun
Host: localhost
Password_last_changed: 2022-06-04 11:17:38
password_lifetime: NULL
password_expired: N
1 row in set (0.00 sec)
ERROR:
No query specified
修改该账户的过期时间:
mysql> ALTER USER 'litaixun'@'localhost' PASSWORD EXPIRE INTERVAL 260 DAY;
Query OK, 0 rows affected (0.01 sec)
mysql> SELECT User, Host, Password_last_changed, password_lifetime, password_expired FROM MySQL.user WHERE User = 'litaixun' \G;
*************************** 1. row ***************************
User: litaixun
Host: localhost
Password_last_changed: 2022-06-04 11:17:38
password_lifetime: 260
password_expired: N
1 row in set (0.00 sec)
ERROR:
No query specified
还原该账户的密码为永不过期:
mysql> ALTER USER 'litaixun'@'localhost' PASSWORD EXPIRE DEFAULT;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT User, Host, Password_last_changed, password_lifetime, password_expired FROM MySQL.user WHERE User = 'litaixun' \G;
*************************** 1. row ***************************
User: litaixun
Host: localhost
Password_last_changed: 2022-06-04 11:17:38
password_lifetime: NULL
password_expired: N
1 row in set (0.00 sec)
ERROR:
No query specified